1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-05 02:29:54 +00:00

Rename Hypher to Hypha

This commit is contained in:
Timur Ismagilov 2022-02-19 11:26:38 +03:00 committed by Timur Ismagilov
parent 4890c21012
commit c0ac87cdbd
34 changed files with 885 additions and 765 deletions

View File

@ -2,6 +2,7 @@
package backlinks
import (
"log"
"os"
"github.com/bouncepaw/mycorrhiza/hyphae"
@ -53,7 +54,7 @@ func IndexBacklinks() {
}
// BacklinksCount returns the amount of backlinks to the hypha.
func BacklinksCount(h hyphae.Hypher) int {
func BacklinksCount(h hyphae.Hypha) int {
if links, exists := backlinkIndex[h.CanonicalName()]; exists {
return len(links)
}
@ -71,16 +72,27 @@ func toLinkSet(xs []string) linkSet {
return result
}
func fetchText(h hyphae.Hypher) string {
if !h.HasTextPart() {
func fetchText(h hyphae.Hypha) string {
var path string
switch h := h.(type) {
case *hyphae.EmptyHypha:
return ""
case *hyphae.TextualHypha:
path = h.TextFilePath()
case *hyphae.MediaHypha:
if !h.HasTextFile() {
return ""
}
path = h.TextFilePath()
}
text, err := os.ReadFile(path)
if err != nil {
log.Println(err)
return ""
}
text, err := os.ReadFile(h.TextPartPath())
if err == nil {
return string(text)
}
return ""
}
// backlinkIndexOperation is an operation for the backlink index. This operation is executed async-safe.
type backlinkIndexOperation interface {

View File

@ -9,26 +9,26 @@ import (
)
// UpdateBacklinksAfterEdit is a creation/editing hook for backlinks index
func UpdateBacklinksAfterEdit(h hyphae.Hypher, oldText string) {
func UpdateBacklinksAfterEdit(h hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.CanonicalName(), oldText)
newLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexEdit{h.CanonicalName(), oldLinks, newLinks}
}
// UpdateBacklinksAfterDelete is a deletion hook for backlinks index
func UpdateBacklinksAfterDelete(h hyphae.Hypher, oldText string) {
func UpdateBacklinksAfterDelete(h hyphae.Hypha, oldText string) {
oldLinks := extractHyphaLinksFromContent(h.CanonicalName(), oldText)
backlinkConveyor <- backlinkIndexDeletion{h.CanonicalName(), oldLinks}
}
// UpdateBacklinksAfterRename is a renaming hook for backlinks index
func UpdateBacklinksAfterRename(h hyphae.Hypher, oldName string) {
func UpdateBacklinksAfterRename(h hyphae.Hypha, oldName string) {
actualLinks := extractHyphaLinks(h)
backlinkConveyor <- backlinkIndexRenaming{oldName, h.CanonicalName(), actualLinks}
}
// extractHyphaLinks extracts hypha links from a desired hypha
func extractHyphaLinks(h hyphae.Hypher) []string {
func extractHyphaLinks(h hyphae.Hypha) []string {
return extractHyphaLinksFromContent(h.CanonicalName(), fetchText(h))
}

View File

@ -17,7 +17,7 @@ func ResetCount() {
count.Unlock()
}
// Count how many hyphae there are.
// Count how many hyphae there are. This is a O(1), the number of hyphae is stored in memory.
func Count() int {
count.Lock()
defer count.Unlock()

View File

@ -12,31 +12,17 @@ func (e *EmptyHypha) CanonicalName() string {
return e.canonicalName
}
func (e *EmptyHypha) HasTextPart() bool {
return false
}
func (e *EmptyHypha) TextPartPath() string {
return ""
}
// NewEmptyHypha returns an empty hypha struct with given name.
func NewEmptyHypha(hyphaName string) *EmptyHypha {
return &EmptyHypha{
canonicalName: hyphaName,
func ExtendEmptyToTextual(e *EmptyHypha, mycoFilePath string) *TextualHypha {
return &TextualHypha{
canonicalName: e.CanonicalName(),
mycoFilePath: mycoFilePath,
}
}
func FillEmptyHyphaUpToTextualHypha(e *EmptyHypha, textPath string) *NonEmptyHypha { // sic!
return &NonEmptyHypha{
name: e.CanonicalName(),
TextPath: textPath,
}
}
func FillEmptyHyphaUpToMediaHypha(e *EmptyHypha, binaryPath string) *NonEmptyHypha { // sic!
return &NonEmptyHypha{
name: e.CanonicalName(),
binaryPath: binaryPath,
func ExtendEmptyToMedia(e *EmptyHypha, mediaFilePath string) *MediaHypha {
return &MediaHypha{
canonicalName: e.CanonicalName(),
mycoFilePath: "",
mediaFilePath: mediaFilePath,
}
}

39
hyphae/existing_hypha.go Normal file
View File

@ -0,0 +1,39 @@
package hyphae
import (
"github.com/bouncepaw/mycorrhiza/util"
)
// ExistingHypha is not EmptyHypha.
type ExistingHypha interface {
Hypha
// DoesExist does nothing except marks that the type is an ExistingHypha.
DoesExist()
HasTextFile() bool
TextFilePath() string
}
// RenameHyphaTo renames a hypha and renames stored filepaths as needed. The actual files are not moved, move them yourself.
func RenameHyphaTo(h ExistingHypha, newName string, replaceName func(string) string) {
// TODO: that replaceName is suspicious.
newName = util.CanonicalName(newName)
byNamesMutex.Lock()
h.Lock()
delete(byNames, h.CanonicalName())
switch h := h.(type) {
case *TextualHypha:
h.canonicalName = newName
h.mycoFilePath = replaceName(h.mycoFilePath)
case *MediaHypha:
h.canonicalName = newName
h.mycoFilePath = replaceName(h.mediaFilePath)
h.mediaFilePath = replaceName(h.mediaFilePath)
}
byNames[h.CanonicalName()] = h
byNamesMutex.Unlock()
h.Unlock()
}

View File

@ -10,34 +10,45 @@ import (
// Index finds all hypha files in the full `path` and saves them to the hypha storage.
func Index(path string) {
byNames = make(map[string]Hypher)
ch := make(chan Hypher, 5)
byNames = make(map[string]ExistingHypha)
ch := make(chan ExistingHypha, 5)
go func(ch chan Hypher) {
go func(ch chan ExistingHypha) {
indexHelper(path, 0, ch)
close(ch)
}(ch)
for nh := range ch {
switch oh := ByName(nh.CanonicalName()).(type) {
for foundHypha := range ch {
switch storedHypha := ByName(foundHypha.CanonicalName()).(type) {
case *EmptyHypha:
Insert(nh)
default:
// In case of conflicts the newer hypha overwrites the previous
switch nh, oh := nh.(*NonEmptyHypha), oh.(*NonEmptyHypha); {
case (nh.Kind() == HyphaText) && (oh.Kind() == HyphaMedia):
oh.TextPath = nh.TextPartPath()
Insert(foundHypha)
case (nh.Kind() == HyphaText) && (oh.Kind() == HyphaText):
log.Printf("File collision for hypha %s, using %s rather than %s\n", nh.CanonicalName(), nh.TextPartPath(), oh.TextPartPath())
oh.TextPath = nh.TextPartPath()
case *TextualHypha:
switch foundHypha := foundHypha.(type) {
case *TextualHypha: // conflict! overwrite
storedHypha.mycoFilePath = foundHypha.mycoFilePath
log.Printf(
"File collision for hypha %s, using %s rather than %s\n",
foundHypha.CanonicalName(),
foundHypha.TextFilePath(),
storedHypha.TextFilePath(),
)
case *MediaHypha: // no conflict
Insert(ExtendTextualToMedia(storedHypha, foundHypha.mediaFilePath))
}
case (nh.Kind() == HyphaMedia) && (oh.Kind() == HyphaMedia):
log.Printf("File collision for hypha %s, using %s rather than %s\n", nh.CanonicalName(), nh.BinaryPath(), oh.BinaryPath())
oh.SetBinaryPath(nh.BinaryPath())
case (nh.Kind() == HyphaMedia) && (oh.Kind() == HyphaText):
oh.SetBinaryPath(nh.BinaryPath())
case *MediaHypha:
switch foundHypha := foundHypha.(type) {
case *TextualHypha: // no conflict
storedHypha.mycoFilePath = foundHypha.mycoFilePath
case *MediaHypha: // conflict! overwrite
storedHypha.mediaFilePath = foundHypha.mediaFilePath
log.Printf(
"File collision for hypha %s, using %s rather than %s\n",
foundHypha.CanonicalName(),
foundHypha.MediaFilePath(),
storedHypha.MediaFilePath(),
)
}
}
}
@ -47,7 +58,7 @@ func Index(path string) {
// 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
// up to the caller.
func indexHelper(path string, nestLevel uint, ch chan Hypher) {
func indexHelper(path string, nestLevel uint, ch chan ExistingHypha) {
nodes, err := os.ReadDir(path)
if err != nil {
log.Fatal(err)
@ -64,15 +75,20 @@ func indexHelper(path string, nestLevel uint, ch chan Hypher) {
var (
hyphaPartPath = filepath.Join(path, node.Name())
hyphaName, isText, skip = mimetype.DataFromFilename(hyphaPartPath)
hypha = &NonEmptyHypha{name: hyphaName, Exists: true}
)
if !skip {
if isText {
hypha.TextPath = hyphaPartPath
ch <- &TextualHypha{
canonicalName: hyphaName,
mycoFilePath: hyphaPartPath,
}
} else {
hypha.SetBinaryPath(hyphaPartPath)
}
ch <- hypha
ch <- &MediaHypha{
canonicalName: hyphaName,
mycoFilePath: "",
mediaFilePath: hyphaPartPath,
}
}
}
}
}

View File

@ -22,25 +22,15 @@ func IsValidName(hyphaName string) bool {
return true
}
type HyphaKind int
const (
HyphaText HyphaKind = iota
HyphaMedia
)
// Hypher is a temporary name for this interface. The name will become NonEmptyHypha, once the struct with the said name is deprecated for good.
type Hypher interface {
// Hypha is a hypha you know and love.
type Hypha interface {
sync.Locker
CanonicalName() string
HasTextPart() bool
TextPartPath() string
}
// DeleteHypha deletes the hypha from the storage.
func DeleteHypha(h Hypher) {
func DeleteHypha(h ExistingHypha) {
byNamesMutex.Lock()
h.Lock()
delete(byNames, h.CanonicalName())
@ -49,19 +39,8 @@ func DeleteHypha(h Hypher) {
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.(*NonEmptyHypha).SetName(newName)
byNames[h.CanonicalName()] = h.(*NonEmptyHypha)
byNamesMutex.Unlock()
h.Unlock()
}
// Insert inserts the hypha into the storage, possibly overwriting the previous hypha with the same name. Count incrementation is done if needed.
func Insert(h Hypher) (madeNewRecord bool) {
// Insert inserts the hypha into the storage, possibly overwriting the previous hypha with the same name. Count incrementation is done if needed. You cannot insert an empty hypha.
func Insert(h ExistingHypha) (madeNewRecord bool) {
_, recorded := byNames[h.CanonicalName()]
byNamesMutex.Lock()
@ -75,23 +54,15 @@ func Insert(h Hypher) (madeNewRecord bool) {
return !recorded
}
// InsertIfNew checks whether the hypha exists and returns `true` if it didn't and has been created.
func InsertIfNew(h Hypher) (madeNewRecord bool) {
switch ByName(h.CanonicalName()).(type) {
case *EmptyHypha:
return Insert(h)
default:
return false
}
}
// ByName returns a hypha by name. It returns an *EmptyHypha if there is no such hypha. This function is the only source of empty hyphae.
func ByName(hyphaName string) (h Hypher) {
func ByName(hyphaName string) (h Hypha) {
byNamesMutex.Lock()
defer byNamesMutex.Unlock()
h, recorded := byNames[hyphaName]
if recorded {
return h
}
return NewEmptyHypha(hyphaName)
return &EmptyHypha{
canonicalName: hyphaName,
}
}

View File

@ -7,20 +7,20 @@ import (
// Iteration represents an iteration over all hyphae in the storage. You may use it instead of directly iterating using hyphae.YieldExistingHyphae when you want to do n checks at once instead of iterating n times.
type Iteration struct {
sync.Mutex
iterator func() chan Hypher
checks []func(h Hypher) CheckResult
iterator func() chan ExistingHypha
checks []func(h Hypha) CheckResult
}
// NewIteration constructs an iteration without checks.
func NewIteration() *Iteration {
return &Iteration{
iterator: YieldExistingHyphae,
checks: make([]func(h Hypher) CheckResult, 0),
checks: make([]func(h Hypha) CheckResult, 0),
}
}
// AddCheck adds the check to the iteration. It is concurrent-safe.
func (i7n *Iteration) AddCheck(check func(h Hypher) CheckResult) {
func (i7n *Iteration) AddCheck(check func(h Hypha) CheckResult) {
i7n.Lock()
i7n.checks = append(i7n.checks, check)
i7n.Unlock()

View File

@ -8,16 +8,15 @@ import (
"sync"
)
var byNames = make(map[string]Hypher)
var byNames = make(map[string]ExistingHypha)
var byNamesMutex = sync.Mutex{}
// YieldExistingHyphae iterates over all hyphae and yields all existing ones.
func YieldExistingHyphae() chan Hypher {
ch := make(chan Hypher)
func YieldExistingHyphae() chan ExistingHypha {
ch := make(chan ExistingHypha)
go func() {
for _, h := range byNames {
switch h.(type) {
case *EmptyHypha:
default:
ch <- h
}
@ -28,13 +27,18 @@ func YieldExistingHyphae() chan Hypher {
}
// FilterHyphaeWithText filters the source channel and yields only those hyphae than have text parts.
func FilterHyphaeWithText(src chan Hypher) chan Hypher {
func FilterHyphaeWithText(src chan ExistingHypha) chan ExistingHypha {
// TODO: reimplement as a function with a callback?
sink := make(chan Hypher)
sink := make(chan ExistingHypha)
go func() {
for h := range src {
if h.HasTextPart() {
switch h := h.(type) {
case *TextualHypha:
sink <- h
case *MediaHypha:
if h.HasTextFile() {
sink <- h
}
}
}
close(sink)
@ -85,8 +89,8 @@ func PathographicSort(src chan string) <-chan string {
}
// Subhyphae returns slice of subhyphae.
func Subhyphae(h Hypher) []Hypher {
var hyphae []Hypher
func Subhyphae(h Hypha) []ExistingHypha {
var hyphae []ExistingHypha
for subh := range YieldExistingHyphae() {
if strings.HasPrefix(subh.CanonicalName(), h.CanonicalName()+"/") {
hyphae = append(hyphae, subh)

48
hyphae/media_hypha.go Normal file
View File

@ -0,0 +1,48 @@
package hyphae
import (
"github.com/bouncepaw/mycorrhiza/files"
"path/filepath"
"sync"
)
type MediaHypha struct {
sync.RWMutex
canonicalName string
mycoFilePath string
mediaFilePath string
}
func (m *MediaHypha) DoesExist() {
}
func (m *MediaHypha) CanonicalName() string {
return m.canonicalName
}
func (m *MediaHypha) TextFilePath() string {
if m.mycoFilePath == "" {
return filepath.Join(files.HyphaeDir(), m.CanonicalName()+".myco")
}
return m.mycoFilePath
}
func (m *MediaHypha) HasTextFile() bool {
return m.mycoFilePath != ""
}
func (m *MediaHypha) MediaFilePath() string {
return m.mediaFilePath
}
func (m *MediaHypha) SetMediaFilePath(newPath string) {
m.mediaFilePath = newPath
}
func ShrinkMediaToTextual(m *MediaHypha) *TextualHypha {
return &TextualHypha{
canonicalName: m.CanonicalName(),
mycoFilePath: m.TextFilePath(),
}
}

View File

@ -1,52 +0,0 @@
// Package hyphae is for the NonEmptyHypha type, hypha storage and stuff like that. It shall not depend on mycorrhiza modules other than util.
package hyphae
import (
"path/filepath"
"sync"
"github.com/bouncepaw/mycorrhiza/files"
)
// NonEmptyHypha keeps vital information about a media hypha
type NonEmptyHypha struct {
sync.RWMutex
name string // Canonical name
Exists bool
TextPath string // == "" => no text part
binaryPath string // == "" => no attachment
}
func (h *NonEmptyHypha) SetName(s string) { h.name = s }
func (h *NonEmptyHypha) BinaryPath() string { return h.binaryPath }
func (h *NonEmptyHypha) SetBinaryPath(s string) { h.binaryPath = s }
func (h *NonEmptyHypha) CanonicalName() string {
return h.name
}
func (h *NonEmptyHypha) Kind() HyphaKind { // sic!
if h.HasAttachment() {
return HyphaMedia
}
return HyphaText
}
func (h *NonEmptyHypha) HasTextPart() bool {
return h.TextPath != ""
}
// TextPartPath returns rooted path to the file where the text part should be.
func (h *NonEmptyHypha) TextPartPath() string {
if h.TextPath == "" {
return filepath.Join(files.HyphaeDir(), h.name+".myco")
}
return h.TextPath
}
// HasAttachment is true if the hypha has an attachment.
func (h *NonEmptyHypha) HasAttachment() bool {
return h.binaryPath != ""
}

35
hyphae/textual_hypha.go Normal file
View File

@ -0,0 +1,35 @@
package hyphae
import (
"sync"
)
type TextualHypha struct {
sync.RWMutex
canonicalName string
mycoFilePath string
}
func (t *TextualHypha) DoesExist() {
}
func (t *TextualHypha) CanonicalName() string {
return t.canonicalName
}
func (t *TextualHypha) HasTextFile() bool {
return true
}
func (t *TextualHypha) TextFilePath() string {
return t.mycoFilePath
}
func ExtendTextualToMedia(t *TextualHypha, mediaFilePath string) *MediaHypha {
return &MediaHypha{
canonicalName: t.CanonicalName(),
mycoFilePath: t.TextFilePath(),
mediaFilePath: mediaFilePath,
}
}

View File

@ -41,10 +41,10 @@ func MigrateRocketsMaybe() {
for hypha := range hyphae.FilterHyphaeWithText(hyphae.YieldExistingHyphae()) {
/// Open file, read from file, modify file. If anything goes wrong, scream and shout.
file, err := os.OpenFile(hypha.TextPartPath(), os.O_RDWR, 0766)
file, err := os.OpenFile(hypha.TextFilePath(), os.O_RDWR, 0766)
if err != nil {
hop.WithErrAbort(err)
log.Fatal("Something went wrong when opening ", hypha.TextPartPath(), ": ", err.Error())
log.Fatal("Something went wrong when opening ", hypha.TextFilePath(), ": ", err.Error())
}
var buf strings.Builder
@ -52,7 +52,7 @@ func MigrateRocketsMaybe() {
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
log.Fatal("Something went wrong when reading ", hypha.TextPartPath(), ": ", err.Error())
log.Fatal("Something went wrong when reading ", hypha.TextFilePath(), ": ", err.Error())
}
var (
@ -60,27 +60,27 @@ func MigrateRocketsMaybe() {
newText = tools.MigrateRocketLinks(oldText)
)
if oldText != newText { // This file right here is being migrated for real.
mycoFiles = append(mycoFiles, hypha.TextPartPath())
mycoFiles = append(mycoFiles, hypha.TextFilePath())
err = file.Truncate(0)
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
log.Fatal("Something went wrong when truncating ", hypha.TextPartPath(), ": ", err.Error())
log.Fatal("Something went wrong when truncating ", hypha.TextFilePath(), ": ", err.Error())
}
_, err = file.Seek(0, 0)
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
log.Fatal("Something went wrong when seeking in ", hypha.TextPartPath(), ": ", err.Error())
log.Fatal("Something went wrong when seeking in ", hypha.TextFilePath(), ": ", err.Error())
}
_, err = file.WriteString(newText)
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
log.Fatal("Something went wrong when writing to ", hypha.TextPartPath(), ": ", err.Error())
log.Fatal("Something went wrong when writing to ", hypha.TextFilePath(), ": ", err.Error())
}
}
_ = file.Close()

View File

@ -11,14 +11,14 @@ import (
// TODO: get rid of this abomination
func canFactory(
rejectLogger func(hyphae.Hypher, *user.User, string),
rejectLogger func(hyphae.Hypha, *user.User, string),
action string,
dispatcher func(hyphae.Hypher, *user.User, *l18n.Localizer) (string, string),
dispatcher func(hyphae.Hypha, *user.User, *l18n.Localizer) (string, string),
noRightsMsg string,
notExistsMsg string,
mustExist bool,
) func(*user.User, hyphae.Hypher, *l18n.Localizer) (string, error) {
return func(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (string, error) {
) func(*user.User, hyphae.Hypha, *l18n.Localizer) (string, error) {
return func(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (string, error) {
if !u.CanProceed(action) {
rejectLogger(h, u, "no rights")
return lc.Get("ui.act_no_rights"), errors.New(lc.Get(noRightsMsg))
@ -66,15 +66,13 @@ var (
CanUnattach = canFactory(
rejectUnattachLog,
"unattach-confirm",
func(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) (errmsg, errtitle string) {
func(h hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errmsg, errtitle string) {
switch h := h.(type) {
case *hyphae.EmptyHypha:
case *hyphae.NonEmptyHypha:
if h.Kind() != hyphae.HyphaMedia {
case *hyphae.TextualHypha:
rejectUnattachLog(h, u, "no amnt")
return lc.Get("ui.act_noattachment_tip"), lc.Get("ui.act_noattachment")
}
}
return "", ""
},

View File

@ -11,23 +11,30 @@ import (
)
// DeleteHypha deletes hypha and makes a history record about that.
func DeleteHypha(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
hop = history.Operation(history.TypeDeleteHypha)
func DeleteHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
hop = history.
Operation(history.TypeDeleteHypha).
WithMsg(fmt.Sprintf("Delete %s", h.CanonicalName())).
WithUser(u)
if errtitle, err := CanDelete(u, h, lc); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
originalText, _ := FetchTextPart(h)
hop.
WithFilesRemoved(h.TextPartPath(), h.(*hyphae.NonEmptyHypha).BinaryPath()).
WithMsg(fmt.Sprintf("Delete %s", h.CanonicalName())).
WithUser(u).
Apply()
switch h := h.(type) {
case *hyphae.MediaHypha:
hop.WithFilesRemoved(h.MediaFilePath(), h.TextFilePath())
case *hyphae.TextualHypha:
hop.WithFilesRemoved(h.TextFilePath())
default:
panic("impossible")
}
originalText, _ := FetchTextFile(h)
hop.Apply()
if !hop.HasErrors() {
backlinks.UpdateBacklinksAfterDelete(h, originalText)
hyphae.DeleteHypha(h)
hyphae.DeleteHypha(h.(hyphae.ExistingHypha)) // we panicked before, so it's safe
}
return hop, ""
}

View File

@ -10,6 +10,7 @@ import (
)
func init() {
// TODO: clean this complete and utter mess
globals.HyphaExists = func(hyphaName string) bool {
switch hyphae.ByName(hyphaName).(type) {
case *hyphae.EmptyHypha:
@ -22,13 +23,12 @@ func init() {
switch h := hyphae.ByName(hyphaName).(type) {
case *hyphae.EmptyHypha:
err = errors.New("Hypha " + hyphaName + " does not exist")
default:
rawText, err = FetchTextPart(h)
if h := h.(*hyphae.NonEmptyHypha); h.Kind() == hyphae.HyphaMedia {
// the view is localized, but we can't pass it, so...
case *hyphae.TextualHypha:
rawText, err = FetchTextFile(h)
case *hyphae.MediaHypha:
rawText, err = FetchTextFile(h)
binaryBlock = views.AttachmentHTMLRaw(h)
}
}
return
}
globals.HyphaIterate = func(λ func(string)) {

View File

@ -7,18 +7,18 @@ import (
"github.com/bouncepaw/mycorrhiza/user"
)
func rejectDeleteLog(h hyphae.Hypher, u *user.User, errmsg string) {
func rejectDeleteLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject delete %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectRenameLog(h hyphae.Hypher, u *user.User, errmsg string) {
func rejectRenameLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject rename %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectUnattachLog(h hyphae.Hypher, u *user.User, errmsg string) {
func rejectUnattachLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject unattach %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectEditLog(h hyphae.Hypher, u *user.User, errmsg string) {
func rejectEditLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject edit %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectAttachLog(h hyphae.Hypher, u *user.User, errmsg string) {
func rejectAttachLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject attach %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}

View File

@ -13,7 +13,7 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
)
func canRenameThisToThat(oh hyphae.Hypher, nh hyphae.Hypher, u *user.User, lc *l18n.Localizer) (errtitle string, err error) {
func canRenameThisToThat(oh hyphae.Hypha, nh hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errtitle string, err error) {
switch nh.(type) {
case *hyphae.EmptyHypha:
default:
@ -35,7 +35,7 @@ func canRenameThisToThat(oh hyphae.Hypher, nh hyphae.Hypher, u *user.User, lc *l
}
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
func RenameHypha(h hyphae.Hypher, newHypha hyphae.Hypher, recursive bool, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
func RenameHypha(h hyphae.Hypha, newHypha hyphae.Hypha, recursive bool, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
newHypha.Lock()
defer newHypha.Unlock()
hop = history.Operation(history.TypeRenameHypha)
@ -54,7 +54,7 @@ func RenameHypha(h hyphae.Hypher, newHypha hyphae.Hypher, recursive bool, u *use
replaceName = func(str string) string {
return re.ReplaceAllString(util.CanonicalName(str), newHypha.CanonicalName())
}
hyphaeToRename = findHyphaeToRename(h, recursive)
hyphaeToRename = findHyphaeToRename(h.(hyphae.ExistingHypha), recursive)
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
renameMsg = "Rename %s to %s"
)
@ -70,47 +70,43 @@ func RenameHypha(h hyphae.Hypher, newHypha hyphae.Hypher, recursive bool, u *use
WithUser(u).
Apply()
if len(hop.Errs) == 0 {
for _, h := range hyphaeToRename {
h := h.(*hyphae.NonEmptyHypha) // ontology think
for _, H := range hyphaeToRename {
h := H.(hyphae.ExistingHypha) // ontology think
oldName := h.CanonicalName()
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()))
h.Lock()
h.TextPath = replaceName(h.TextPath)
h.SetBinaryPath(replaceName(h.BinaryPath()))
h.Unlock()
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()), replaceName)
backlinks.UpdateBacklinksAfterRename(h, oldName)
}
}
return hop, ""
}
func findHyphaeToRename(superhypha hyphae.Hypher, recursive bool) []hyphae.Hypher {
hyphaList := []hyphae.Hypher{superhypha}
func findHyphaeToRename(superhypha hyphae.ExistingHypha, recursive bool) []hyphae.ExistingHypha {
hyphaList := []hyphae.ExistingHypha{superhypha}
if recursive {
hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
}
return hyphaList
}
func renamingPairs(hyphaeToRename []hyphae.Hypher, replaceName func(string) string) (map[string]string, error) {
renameMap := make(map[string]string)
newNames := make([]string, len(hyphaeToRename))
func renamingPairs(hyphaeToRename []hyphae.ExistingHypha, replaceName func(string) string) (map[string]string, error) {
var (
renameMap = make(map[string]string)
newNames = make([]string, len(hyphaeToRename))
)
for _, h := range hyphaeToRename {
h.Lock()
newNames = append(newNames, replaceName(h.CanonicalName()))
if h.HasTextPart() {
renameMap[h.TextPartPath()] = replaceName(h.TextPartPath())
if h.HasTextFile() {
renameMap[h.TextFilePath()] = replaceName(h.TextFilePath())
}
switch h := h.(type) {
case *hyphae.NonEmptyHypha:
if h.Kind() == hyphae.HyphaMedia { // ontology think
renameMap[h.BinaryPath()] = replaceName(h.BinaryPath())
}
case *hyphae.MediaHypha:
renameMap[h.MediaFilePath()] = replaceName(h.MediaFilePath())
}
h.Unlock()
}
if firstFailure, ok := hyphae.AreFreeNames(newNames...); !ok {
return nil, errors.New("NonEmptyHypha " + firstFailure + " already exists")
return nil, errors.New("Hypha " + firstFailure + " already exists")
}
return renameMap, nil
}

View File

@ -10,17 +10,17 @@ import (
)
// UnattachHypha unattaches hypha and makes a history record about that.
func UnattachHypha(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
hop = history.Operation(history.TypeUnattachHypha)
if errtitle, err := CanUnattach(u, h, lc); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
H := h.(*hyphae.NonEmptyHypha)
H := h.(*hyphae.MediaHypha)
hop.
WithFilesRemoved(H.BinaryPath()).
WithFilesRemoved(H.MediaFilePath()).
WithMsg(fmt.Sprintf("Unattach %s", h.CanonicalName())).
WithUser(u).
Apply()
@ -31,12 +31,10 @@ func UnattachHypha(u *user.User, h hyphae.Hypher, 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"
}
if H.BinaryPath() != "" {
H.SetBinaryPath("")
}
// If nothing is left of the hypha
if H.TextPath == "" {
hyphae.DeleteHypha(h)
if H.HasTextFile() {
hyphae.Insert(hyphae.ShrinkMediaToTextual(H))
} else {
hyphae.DeleteHypha(H)
}
return hop, ""
}

View File

@ -18,7 +18,7 @@ import (
"path/filepath"
)
func historyMessageForTextUpload(h hyphae.Hypher, userMessage string) string {
func historyMessageForTextUpload(h hyphae.Hypha, userMessage string) string {
var verb string
switch h.(type) {
case *hyphae.EmptyHypha:
@ -33,21 +33,21 @@ func historyMessageForTextUpload(h hyphae.Hypher, userMessage string) string {
return fmt.Sprintf("%s %s: %s", verb, h.CanonicalName(), userMessage)
}
func writeTextToDisk(h *hyphae.NonEmptyHypha, data []byte, hop *history.Op) error {
if err := os.MkdirAll(filepath.Dir(h.TextPartPath()), 0777); err != nil {
func writeTextToDisk(h hyphae.ExistingHypha, data []byte, hop *history.Op) error {
if err := os.MkdirAll(filepath.Dir(h.TextFilePath()), 0777); err != nil {
return err
}
if err := os.WriteFile(h.TextPartPath(), data, 0666); err != nil {
if err := os.WriteFile(h.TextFilePath(), data, 0666); err != nil {
return err
}
hop.WithFiles(h.TextPartPath())
hop.WithFiles(h.TextFilePath())
return nil
}
// UploadText edits the hypha's text part and makes a history record about that.
func UploadText(h hyphae.Hypher, data []byte, userMessage string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
hop = history.
Operation(history.TypeEditText).
WithMsg(historyMessageForTextUpload(h, userMessage)).
@ -68,27 +68,24 @@ func UploadText(h hyphae.Hypher, data []byte, userMessage string, u *user.User,
// Empty data check
if len(bytes.TrimSpace(data)) == 0 { // if nothing but whitespace
switch h := h.(type) {
switch h.(type) {
case *hyphae.EmptyHypha:
// It's ok, just like cancel button.
return hop.Abort(), ""
case *hyphae.NonEmptyHypha:
switch h.Kind() {
case hyphae.HyphaMedia:
case *hyphae.MediaHypha:
// Writing no description, it's ok, just like cancel button.
return hop.Abort(), ""
case hyphae.HyphaText:
case *hyphae.TextualHypha:
// What do you want passing nothing for a textual hypha?
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
}
}
}
// At this point, we have a savable user-generated Mycomarkup document. Gotta save it.
switch h := h.(type) {
case *hyphae.EmptyHypha:
H := hyphae.FillEmptyHyphaUpToTextualHypha(h, filepath.Join(files.HyphaeDir(), h.CanonicalName()+".myco"))
H := hyphae.ExtendEmptyToTextual(h, filepath.Join(files.HyphaeDir(), h.CanonicalName()+".myco"))
err := writeTextToDisk(H, data, hop)
if err != nil {
@ -96,8 +93,26 @@ func UploadText(h hyphae.Hypher, data []byte, userMessage string, u *user.User,
}
hyphae.Insert(H)
case *hyphae.NonEmptyHypha:
oldText, err := FetchTextPart(h)
case *hyphae.MediaHypha:
oldText, err := FetchTextFile(h)
if err != nil {
return hop.WithErrAbort(err), err.Error()
}
// TODO: that []byte(...) part should be removed
if bytes.Compare(data, []byte(oldText)) == 0 {
// No changes! Just like cancel button
return hop.Abort(), ""
}
err = writeTextToDisk(h, data, hop)
if err != nil {
return hop.WithErrAbort(err), err.Error()
}
backlinks.UpdateBacklinksAfterEdit(h, oldText)
case *hyphae.TextualHypha:
oldText, err := FetchTextFile(h)
if err != nil {
return hop.WithErrAbort(err), err.Error()
}
@ -119,12 +134,12 @@ func UploadText(h hyphae.Hypher, data []byte, userMessage string, u *user.User,
return hop.Apply(), ""
}
func historyMessageForMediaUpload(h hyphae.Hypher, mime string) string {
func historyMessageForMediaUpload(h hyphae.Hypha, mime string) string {
return fmt.Sprintf("Upload media for %s with type %s", h.CanonicalName(), mime)
}
// writeMediaToDisk saves the given data with the given mime type for the given hypha to the disk and returns the path to the saved file and an error, if any.
func writeMediaToDisk(h hyphae.Hypher, mime string, data []byte) (string, error) {
func writeMediaToDisk(h hyphae.Hypha, mime string, data []byte) (string, error) {
var (
ext = mimetype.ToExtension(mime)
// That's where the file will go
@ -142,7 +157,7 @@ func writeMediaToDisk(h hyphae.Hypher, mime string, data []byte) (string, error)
}
// UploadBinary edits the hypha's media part and makes a history record about that.
func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
func UploadBinary(h hyphae.Hypha, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
hop := history.
Operation(history.TypeEditBinary).
WithMsg(historyMessageForMediaUpload(h, mime)).
@ -180,21 +195,18 @@ func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.Use
switch h := h.(type) {
case *hyphae.EmptyHypha:
H := hyphae.FillEmptyHyphaUpToMediaHypha(h, uploadedFilePath)
H := hyphae.ExtendEmptyToMedia(h, uploadedFilePath)
hyphae.Insert(H)
case *hyphae.NonEmptyHypha:
switch h.Kind() {
case hyphae.HyphaText:
h.SetBinaryPath(uploadedFilePath)
case hyphae.HyphaMedia: // If this is not the first media the hypha gets
prevFilePath := h.BinaryPath()
case *hyphae.TextualHypha:
hyphae.Insert(hyphae.ExtendTextualToMedia(h, uploadedFilePath))
case *hyphae.MediaHypha: // If this is not the first media the hypha gets
prevFilePath := h.MediaFilePath()
if prevFilePath != uploadedFilePath {
if err := history.Rename(prevFilePath, uploadedFilePath); err != nil {
return hop.WithErrAbort(err), err.Error()
}
log.Printf("Move %s to %s\n", prevFilePath, uploadedFilePath)
h.SetBinaryPath(uploadedFilePath)
}
h.SetMediaFilePath(uploadedFilePath)
}
}

View File

@ -8,16 +8,24 @@ import (
"github.com/bouncepaw/mycorrhiza/hyphae"
)
// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
func FetchTextPart(h hyphae.Hypher) (string, error) {
switch h.(type) {
// FetchTextFile tries to read text file of the given hypha. If there is no file, empty string is returned.
func FetchTextFile(h hyphae.Hypha) (string, error) {
switch h := h.(type) {
case *hyphae.EmptyHypha:
return "", errors.New("empty hyphae have no text")
}
if !h.HasTextPart() {
case *hyphae.MediaHypha:
if !h.HasTextFile() {
return "", nil
}
text, err := os.ReadFile(h.TextPartPath())
text, err := os.ReadFile(h.TextFilePath())
if os.IsNotExist(err) {
return "", nil
} else if err != nil {
return "", err
}
return string(text), nil
case *hyphae.TextualHypha:
text, err := os.ReadFile(h.TextFilePath())
if os.IsNotExist(err) {
return "", nil
} else if err != nil {
@ -25,14 +33,16 @@ func FetchTextPart(h hyphae.Hypher) (string, error) {
}
return string(text), nil
}
panic("unreachable")
}
// SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values.
func SetHeaderLinks() {
switch userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha).(type) {
case *hyphae.EmptyHypha:
cfg.SetDefaultHeaderLinks()
default:
contents, err := os.ReadFile(userLinksHypha.TextPartPath())
case hyphae.ExistingHypha:
contents, err := os.ReadFile(userLinksHypha.TextFilePath())
if err != nil || len(contents) == 0 {
cfg.SetDefaultHeaderLinks()
} else {

View File

@ -18,7 +18,7 @@ func findSiblings(hyphaName string) []*sibling {
}
var (
siblingsMap = make(map[string]bool)
siblingCheck = func(h hyphae.Hypher) hyphae.CheckResult {
siblingCheck = func(h hyphae.Hypha) hyphae.CheckResult {
switch {
case h.CanonicalName() == hyphaName, // NonEmptyHypha is no sibling of itself
h.CanonicalName() == parentHyphaName: // Parent hypha is no sibling of its child
@ -63,7 +63,7 @@ func findSiblings(hyphaName string) []*sibling {
func countSubhyphae(siblings []*sibling) {
var (
subhyphaCheck = func(h hyphae.Hypher) hyphae.CheckResult {
subhyphaCheck = func(h hyphae.Hypha) hyphae.CheckResult {
for _, s := range siblings {
if path.Dir(h.CanonicalName()) == s.name {
s.directSubhyphaeCount++

View File

@ -9,10 +9,10 @@
{% import "github.com/bouncepaw/mycorrhiza/history" %}
{% func PrimitiveDiffHTML(rq *http.Request, h hyphae.Hypher, u *user.User, hash string) %}
{% func PrimitiveDiffHTML(rq *http.Request, h hyphae.ExistingHypha, u *user.User, hash string) %}
{% code
lc := l18n.FromRequest(rq)
text, err := history.PrimitiveDiffAtRevision(h.TextPartPath(), hash)
text, err := history.PrimitiveDiffAtRevision(h.TextFilePath(), hash)
if err != nil {
text = err.Error()
}

View File

@ -42,13 +42,13 @@ var (
)
//line views/history.qtpl:12
func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypher, u *user.User, hash string) {
func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.ExistingHypha, u *user.User, hash string) {
//line views/history.qtpl:12
qw422016.N().S(`
`)
//line views/history.qtpl:14
lc := l18n.FromRequest(rq)
text, err := history.PrimitiveDiffAtRevision(h.TextPartPath(), hash)
text, err := history.PrimitiveDiffAtRevision(h.TextFilePath(), hash)
if err != nil {
text = err.Error()
}
@ -76,7 +76,7 @@ func StreamPrimitiveDiffHTML(qw422016 *qt422016.Writer, rq *http.Request, h hyph
}
//line views/history.qtpl:28
func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypher, u *user.User, hash string) {
func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.ExistingHypha, u *user.User, hash string) {
//line views/history.qtpl:28
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/history.qtpl:28
@ -87,7 +87,7 @@ func WritePrimitiveDiffHTML(qq422016 qtio422016.Writer, rq *http.Request, h hyph
}
//line views/history.qtpl:28
func PrimitiveDiffHTML(rq *http.Request, h hyphae.Hypher, u *user.User, hash string) string {
func PrimitiveDiffHTML(rq *http.Request, h hyphae.ExistingHypha, u *user.User, hash string) string {
//line views/history.qtpl:28
qb422016 := qt422016.AcquireByteBuffer()
//line views/history.qtpl:28

View File

@ -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 nonExistentHyphaNotice(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) %}
{% func nonExistentHyphaNotice(h hyphae.Hypha, u *user.User, lc *l18n.Localizer) %}
<section class="non-existent-hypha">
<h2 class="non-existent-hypha__title">{%s lc.Get("ui.notexist_heading") %}</h2>
{% if cfg.UseAuth && u.Group == "anon" %}
@ -47,7 +47,7 @@
</section>
{% endfunc %}
{% func NaviTitleHTML(h hyphae.Hypher) %}
{% func NaviTitleHTML(h hyphae.Hypha) %}
{% code
var (
prevAcc = "/hypha/"
@ -75,10 +75,10 @@
</h1>
{% endfunc %}
{% func AttachmentHTMLRaw(h *hyphae.NonEmptyHypha) %}{%= AttachmentHTML(h, l18n.New("en", "en")) %}{% endfunc %}
{% func AttachmentHTMLRaw(h *hyphae.MediaHypha) %}{%= AttachmentHTML(h, l18n.New("en", "en")) %}{% endfunc %}
{% func AttachmentHTML(h *hyphae.NonEmptyHypha, lc *l18n.Localizer) %}
{% switch filepath.Ext(h.BinaryPath()) %}
{% func AttachmentHTML(h *hyphae.MediaHypha, lc *l18n.Localizer) %}
{% switch filepath.Ext(h.MediaFilePath()) %}
{% case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico" %}
<div class="binary-container binary-container_with-img">

View File

@ -117,7 +117,7 @@ func mycoLink(lc *l18n.Localizer) string {
}
//line views/hypha.qtpl:14
func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h hyphae.Hypher, u *user.User, lc *l18n.Localizer) {
func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h hyphae.Hypha, u *user.User, lc *l18n.Localizer) {
//line views/hypha.qtpl:14
qw422016.N().S(`
<section class="non-existent-hypha">
@ -230,7 +230,7 @@ func streamnonExistentHyphaNotice(qw422016 *qt422016.Writer, h hyphae.Hypher, u
}
//line views/hypha.qtpl:48
func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h hyphae.Hypher, u *user.User, lc *l18n.Localizer) {
func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h hyphae.Hypha, u *user.User, lc *l18n.Localizer) {
//line views/hypha.qtpl:48
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:48
@ -241,7 +241,7 @@ func writenonExistentHyphaNotice(qq422016 qtio422016.Writer, h hyphae.Hypher, u
}
//line views/hypha.qtpl:48
func nonExistentHyphaNotice(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) string {
func nonExistentHyphaNotice(h hyphae.Hypha, u *user.User, lc *l18n.Localizer) string {
//line views/hypha.qtpl:48
qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:48
@ -256,7 +256,7 @@ func nonExistentHyphaNotice(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) s
}
//line views/hypha.qtpl:50
func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h hyphae.Hypher) {
func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h hyphae.Hypha) {
//line views/hypha.qtpl:50
qw422016.N().S(`
`)
@ -323,7 +323,7 @@ func StreamNaviTitleHTML(qw422016 *qt422016.Writer, h hyphae.Hypher) {
}
//line views/hypha.qtpl:76
func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h hyphae.Hypher) {
func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h hyphae.Hypha) {
//line views/hypha.qtpl:76
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:76
@ -334,7 +334,7 @@ func WriteNaviTitleHTML(qq422016 qtio422016.Writer, h hyphae.Hypher) {
}
//line views/hypha.qtpl:76
func NaviTitleHTML(h hyphae.Hypher) string {
func NaviTitleHTML(h hyphae.Hypha) string {
//line views/hypha.qtpl:76
qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:76
@ -349,14 +349,14 @@ func NaviTitleHTML(h hyphae.Hypher) string {
}
//line views/hypha.qtpl:78
func StreamAttachmentHTMLRaw(qw422016 *qt422016.Writer, h *hyphae.NonEmptyHypha) {
func StreamAttachmentHTMLRaw(qw422016 *qt422016.Writer, h *hyphae.MediaHypha) {
//line views/hypha.qtpl:78
StreamAttachmentHTML(qw422016, h, l18n.New("en", "en"))
//line views/hypha.qtpl:78
}
//line views/hypha.qtpl:78
func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h *hyphae.NonEmptyHypha) {
func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h *hyphae.MediaHypha) {
//line views/hypha.qtpl:78
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:78
@ -367,7 +367,7 @@ func WriteAttachmentHTMLRaw(qq422016 qtio422016.Writer, h *hyphae.NonEmptyHypha)
}
//line views/hypha.qtpl:78
func AttachmentHTMLRaw(h *hyphae.NonEmptyHypha) string {
func AttachmentHTMLRaw(h *hyphae.MediaHypha) string {
//line views/hypha.qtpl:78
qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:78
@ -382,12 +382,12 @@ func AttachmentHTMLRaw(h *hyphae.NonEmptyHypha) string {
}
//line views/hypha.qtpl:80
func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.NonEmptyHypha, lc *l18n.Localizer) {
func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.MediaHypha, lc *l18n.Localizer) {
//line views/hypha.qtpl:80
qw422016.N().S(`
`)
//line views/hypha.qtpl:81
switch filepath.Ext(h.BinaryPath()) {
switch filepath.Ext(h.MediaFilePath()) {
//line views/hypha.qtpl:83
case ".jpg", ".gif", ".png", ".webp", ".svg", ".ico":
//line views/hypha.qtpl:83
@ -486,7 +486,7 @@ func StreamAttachmentHTML(qw422016 *qt422016.Writer, h *hyphae.NonEmptyHypha, lc
}
//line views/hypha.qtpl:109
func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.NonEmptyHypha, lc *l18n.Localizer) {
func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.MediaHypha, lc *l18n.Localizer) {
//line views/hypha.qtpl:109
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/hypha.qtpl:109
@ -497,7 +497,7 @@ func WriteAttachmentHTML(qq422016 qtio422016.Writer, h *hyphae.NonEmptyHypha, lc
}
//line views/hypha.qtpl:109
func AttachmentHTML(h *hyphae.NonEmptyHypha, lc *l18n.Localizer) string {
func AttachmentHTML(h *hyphae.MediaHypha, lc *l18n.Localizer) string {
//line views/hypha.qtpl:109
qb422016 := qt422016.AcquireByteBuffer()
//line views/hypha.qtpl:109

View File

@ -5,7 +5,7 @@
{% import "github.com/bouncepaw/mycorrhiza/user" %}
{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
{% func hyphaInfoEntry(h hyphae.Hypher, u *user.User, action, displayText string) %}
{% func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) %}
{% if u.CanProceed(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>
@ -13,7 +13,7 @@
{% endif %}
{% endfunc %}
{% func hyphaInfo(rq *http.Request, h hyphae.Hypher) %}
{% func hyphaInfo(rq *http.Request, h hyphae.Hypha) %}
{% code
u := user.FromRequest(rq)
lc := l18n.FromRequest(rq)

View File

@ -36,7 +36,7 @@ var (
)
//line views/nav.qtpl:8
func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypher, u *user.User, action, displayText string) {
func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) {
//line views/nav.qtpl:8
qw422016.N().S(`
`)
@ -73,7 +73,7 @@ func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypher, u *user.Us
}
//line views/nav.qtpl:14
func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypher, u *user.User, action, displayText string) {
func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) {
//line views/nav.qtpl:14
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/nav.qtpl:14
@ -84,7 +84,7 @@ func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypher, u *user.Us
}
//line views/nav.qtpl:14
func hyphaInfoEntry(h hyphae.Hypher, u *user.User, action, displayText string) string {
func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) string {
//line views/nav.qtpl:14
qb422016 := qt422016.AcquireByteBuffer()
//line views/nav.qtpl:14
@ -99,7 +99,7 @@ func hyphaInfoEntry(h hyphae.Hypher, u *user.User, action, displayText string) s
}
//line views/nav.qtpl:16
func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypher) {
func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha) {
//line views/nav.qtpl:16
qw422016.N().S(`
`)
@ -149,7 +149,7 @@ func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hyphe
}
//line views/nav.qtpl:32
func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypher) {
func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha) {
//line views/nav.qtpl:32
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/nav.qtpl:32
@ -160,7 +160,7 @@ func writehyphaInfo(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hyphe
}
//line views/nav.qtpl:32
func hyphaInfo(rq *http.Request, h hyphae.Hypher) string {
func hyphaInfo(rq *http.Request, h hyphae.Hypha) string {
//line views/nav.qtpl:32
qb422016 := qt422016.AcquireByteBuffer()
//line views/nav.qtpl:32

View File

@ -11,25 +11,26 @@
{% import "github.com/bouncepaw/mycorrhiza/user" %}
{% import "github.com/bouncepaw/mycorrhiza/util" %}
{% func AttachmentMenuHTML(rq *http.Request, h *hyphae.NonEmptyHypha, u *user.User) %}
{% func AttachmentMenuHTML(rq *http.Request, h hyphae.Hypha, u *user.User) %}
{% code
lc := l18n.FromRequest(rq)
%}
<div class="layout">
<main class="main-width attachment-tab">
<h1>{%s= lc.Get("ui.attach_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())}) %}</h1>
{% if h.BinaryPath() == "" %}
<p class="explanation">{%s lc.Get("ui.attach_empty") %} <a href="/help/en/attachment" class="shy-link">{%s lc.Get("ui.attach_link") %}</a></p>
{% else %}
{% switch h.(type) %}
{% case *hyphae.MediaHypha %}
<p class="explanation">{%s lc.Get("ui.attach_tip") %} <a href="/help/en/attachment" class="shy-link">{%s lc.Get("ui.attach_link") %}</a></p>
{% endif %}
{% default %}
<p class="explanation">{%s lc.Get("ui.attach_empty") %} <a href="/help/en/attachment" class="shy-link">{%s lc.Get("ui.attach_link") %}</a></p>
{% endswitch %}
<section class="amnt-grid">
{% if h.BinaryPath() != "" %}
{% switch h := h.(type) %}
{% case *hyphae.MediaHypha %}
{% code
mime := mimetype.FromExtension(path.Ext(h.BinaryPath()))
fileinfo, err := os.Stat(h.BinaryPath()) %}
mime := mimetype.FromExtension(path.Ext(h.MediaFilePath()))
fileinfo, err := os.Stat(h.MediaFilePath()) %}
{% if err == nil %}
<fieldset class="amnt-menu-block">
<legend class="modal__title modal__title_small">{%s lc.Get("ui.attach_stat") %}</legend>
@ -45,7 +46,7 @@
<pre class="codeblock"><code>img { {%s h.CanonicalName() %} }</code></pre>
</fieldset>
{% endif %}
{% endif %}
{% endswitch %}
{% if u.CanProceed("upload-binary") %}
<form action="/upload-binary/{%s h.CanonicalName() %}"
@ -62,7 +63,10 @@
</form>
{% endif %}
{% if h.BinaryPath() != "" && u.CanProceed("unattach-confirm") %}
{% switch h := h.(type) %}
{% case *hyphae.MediaHypha %}
{% if u.CanProceed("unattach-confirm") %}
<form action="/unattach-confirm/{%s h.CanonicalName() %}" method="post" class="modal amnt-menu-block">
<fieldset class="modal__fieldset">
<legend class="modal__title modal__title_small">{%s lc.Get("ui.attach_remove") %}</legend>
@ -71,6 +75,7 @@
</fieldset>
</form>
{% endif %}
{% endswitch %}
</section>
</main>
@ -80,7 +85,7 @@
If `contents` == "", a helpful message is shown instead.
If you rename .prevnext, change the docs too.
{% func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) %}
{% func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents string) %}
{% code
siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
u := user.FromRequest(rq)
@ -131,7 +136,7 @@ If you rename .prevnext, change the docs too.
{%= viewScripts() %}
{% endfunc %}
{% func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) %}
{% func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) %}
{% code
siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName())
%}

View File

@ -51,7 +51,7 @@ var (
)
//line views/readers.qtpl:14
func StreamAttachmentMenuHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hyphae.NonEmptyHypha, u *user.User) {
func StreamAttachmentMenuHTML(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
//line views/readers.qtpl:14
qw422016.N().S(`
`)
@ -69,562 +69,578 @@ func StreamAttachmentMenuHTML(qw422016 *qt422016.Writer, rq *http.Request, h *hy
qw422016.N().S(`</h1>
`)
//line views/readers.qtpl:21
if h.BinaryPath() == "" {
//line views/readers.qtpl:21
switch h.(type) {
//line views/readers.qtpl:22
case *hyphae.MediaHypha:
//line views/readers.qtpl:22
qw422016.N().S(`
<p class="explanation">`)
//line views/readers.qtpl:22
qw422016.E().S(lc.Get("ui.attach_empty"))
//line views/readers.qtpl:22
qw422016.N().S(` <a href="/help/en/attachment" class="shy-link">`)
//line views/readers.qtpl:22
qw422016.E().S(lc.Get("ui.attach_link"))
//line views/readers.qtpl:22
qw422016.N().S(`</a></p>
`)
//line views/readers.qtpl:23
} else {
//line views/readers.qtpl:23
qw422016.N().S(`
<p class="explanation">`)
//line views/readers.qtpl:24
qw422016.E().S(lc.Get("ui.attach_tip"))
//line views/readers.qtpl:24
//line views/readers.qtpl:23
qw422016.N().S(` <a href="/help/en/attachment" class="shy-link">`)
//line views/readers.qtpl:24
//line views/readers.qtpl:23
qw422016.E().S(lc.Get("ui.attach_link"))
//line views/readers.qtpl:24
//line views/readers.qtpl:23
qw422016.N().S(`</a></p>
`)
//line views/readers.qtpl:24
default:
//line views/readers.qtpl:24
qw422016.N().S(`
<p class="explanation">`)
//line views/readers.qtpl:25
qw422016.E().S(lc.Get("ui.attach_empty"))
//line views/readers.qtpl:25
qw422016.N().S(` <a href="/help/en/attachment" class="shy-link">`)
//line views/readers.qtpl:25
qw422016.E().S(lc.Get("ui.attach_link"))
//line views/readers.qtpl:25
qw422016.N().S(`</a></p>
`)
//line views/readers.qtpl:26
}
//line views/readers.qtpl:25
//line views/readers.qtpl:26
qw422016.N().S(`
<section class="amnt-grid">
`)
//line views/readers.qtpl:29
if h.BinaryPath() != "" {
//line views/readers.qtpl:29
switch h := h.(type) {
//line views/readers.qtpl:30
case *hyphae.MediaHypha:
//line views/readers.qtpl:30
qw422016.N().S(`
`)
//line views/readers.qtpl:31
mime := mimetype.FromExtension(path.Ext(h.BinaryPath()))
fileinfo, err := os.Stat(h.BinaryPath())
//line views/readers.qtpl:32
mime := mimetype.FromExtension(path.Ext(h.MediaFilePath()))
fileinfo, err := os.Stat(h.MediaFilePath())
//line views/readers.qtpl:33
qw422016.N().S(`
`)
//line views/readers.qtpl:33
//line views/readers.qtpl:34
if err == nil {
//line views/readers.qtpl:33
//line views/readers.qtpl:34
qw422016.N().S(`
<fieldset class="amnt-menu-block">
<legend class="modal__title modal__title_small">`)
//line views/readers.qtpl:35
//line views/readers.qtpl:36
qw422016.E().S(lc.Get("ui.attach_stat"))
//line views/readers.qtpl:35
//line views/readers.qtpl:36
qw422016.N().S(`</legend>
<p class="modal__confirmation-msg"><b>`)
//line views/readers.qtpl:36
//line views/readers.qtpl:37
qw422016.E().S(lc.Get("ui.attach_stat_size"))
//line views/readers.qtpl:36
//line views/readers.qtpl:37
qw422016.N().S(`</b> `)
//line views/readers.qtpl:36
//line views/readers.qtpl:37
qw422016.E().S(lc.GetPlural64("ui.attach_size_value", fileinfo.Size()))
//line views/readers.qtpl:36
//line views/readers.qtpl:37
qw422016.N().S(`</p>
<p><b>`)
//line views/readers.qtpl:37
//line views/readers.qtpl:38
qw422016.E().S(lc.Get("ui.attach_stat_mime"))
//line views/readers.qtpl:37
//line views/readers.qtpl:38
qw422016.N().S(`</b> `)
//line views/readers.qtpl:37
//line views/readers.qtpl:38
qw422016.E().S(mime)
//line views/readers.qtpl:37
//line views/readers.qtpl:38
qw422016.N().S(`</p>
</fieldset>
`)
//line views/readers.qtpl:39
//line views/readers.qtpl:40
}
//line views/readers.qtpl:39
//line views/readers.qtpl:40
qw422016.N().S(`
`)
//line views/readers.qtpl:41
//line views/readers.qtpl:42
if strings.HasPrefix(mime, "image/") {
//line views/readers.qtpl:41
//line views/readers.qtpl:42
qw422016.N().S(`
<fieldset class="amnt-menu-block">
<legend class="modal__title modal__title_small">`)
//line views/readers.qtpl:43
//line views/readers.qtpl:44
qw422016.E().S(lc.Get("ui.attach_include"))
//line views/readers.qtpl:43
//line views/readers.qtpl:44
qw422016.N().S(`</legend>
<p class="modal__confirmation-msg">`)
//line views/readers.qtpl:44
//line views/readers.qtpl:45
qw422016.E().S(lc.Get("ui.attach_include_tip"))
//line views/readers.qtpl:44
//line views/readers.qtpl:45
qw422016.N().S(`</p>
<pre class="codeblock"><code>img { `)
//line views/readers.qtpl:45
//line views/readers.qtpl:46
qw422016.E().S(h.CanonicalName())
//line views/readers.qtpl:45
//line views/readers.qtpl:46
qw422016.N().S(` }</code></pre>
</fieldset>
`)
//line views/readers.qtpl:47
//line views/readers.qtpl:48
}
//line views/readers.qtpl:47
//line views/readers.qtpl:48
qw422016.N().S(`
`)
//line views/readers.qtpl:48
//line views/readers.qtpl:49
}
//line views/readers.qtpl:48
//line views/readers.qtpl:49
qw422016.N().S(`
`)
//line views/readers.qtpl:50
//line views/readers.qtpl:51
if u.CanProceed("upload-binary") {
//line views/readers.qtpl:50
//line views/readers.qtpl:51
qw422016.N().S(`
<form action="/upload-binary/`)
//line views/readers.qtpl:51
//line views/readers.qtpl:52
qw422016.E().S(h.CanonicalName())
//line views/readers.qtpl:51
//line views/readers.qtpl:52
qw422016.N().S(`"
method="post" enctype="multipart/form-data"
class="upload-binary modal amnt-menu-block">
<fieldset class="modal__fieldset">
<legend class="modal__title modal__title_small">`)
//line views/readers.qtpl:55
//line views/readers.qtpl:56
qw422016.E().S(lc.Get("ui.attach_new"))
//line views/readers.qtpl:55
//line views/readers.qtpl:56
qw422016.N().S(`</legend>
<p class="modal__confirmation-msg">`)
//line views/readers.qtpl:56
//line views/readers.qtpl:57
qw422016.E().S(lc.Get("ui.attach_new_tip"))
//line views/readers.qtpl:56
//line views/readers.qtpl:57
qw422016.N().S(`</p>
<label for="upload-binary__input"></label>
<input type="file" id="upload-binary__input" name="binary">
<button type="submit" class="btn stick-to-bottom" value="Upload">`)
//line views/readers.qtpl:60
//line views/readers.qtpl:61
qw422016.E().S(lc.Get("ui.attach_upload"))
//line views/readers.qtpl:60
//line views/readers.qtpl:61
qw422016.N().S(`</button>
</fieldset>
</form>
`)
//line views/readers.qtpl:63
//line views/readers.qtpl:64
}
//line views/readers.qtpl:63
//line views/readers.qtpl:64
qw422016.N().S(`
`)
//line views/readers.qtpl:65
if h.BinaryPath() != "" && u.CanProceed("unattach-confirm") {
//line views/readers.qtpl:65
//line views/readers.qtpl:67
switch h := h.(type) {
//line views/readers.qtpl:68
case *hyphae.MediaHypha:
//line views/readers.qtpl:68
qw422016.N().S(`
`)
//line views/readers.qtpl:69
if u.CanProceed("unattach-confirm") {
//line views/readers.qtpl:69
qw422016.N().S(`
<form action="/unattach-confirm/`)
//line views/readers.qtpl:66
//line views/readers.qtpl:70
qw422016.E().S(h.CanonicalName())
//line views/readers.qtpl:66
//line views/readers.qtpl:70
qw422016.N().S(`" method="post" class="modal amnt-menu-block">
<fieldset class="modal__fieldset">
<legend class="modal__title modal__title_small">`)
//line views/readers.qtpl:68
//line views/readers.qtpl:72
qw422016.E().S(lc.Get("ui.attach_remove"))
//line views/readers.qtpl:68
//line views/readers.qtpl:72
qw422016.N().S(`</legend>
<p class="modal__confirmation-msg">`)
//line views/readers.qtpl:69
//line views/readers.qtpl:73
qw422016.E().S(lc.Get("ui.attach_remove_tip"))
//line views/readers.qtpl:69
//line views/readers.qtpl:73
qw422016.N().S(`</p>
<button type="submit" class="btn" value="Unattach">`)
//line views/readers.qtpl:70
//line views/readers.qtpl:74
qw422016.E().S(lc.Get("ui.attach_remove_button"))
//line views/readers.qtpl:70
//line views/readers.qtpl:74
qw422016.N().S(`</button>
</fieldset>
</form>
`)
//line views/readers.qtpl:73
//line views/readers.qtpl:77
}
//line views/readers.qtpl:73
//line views/readers.qtpl:77
qw422016.N().S(`
`)
//line views/readers.qtpl:78
}
//line views/readers.qtpl:78
qw422016.N().S(`
</section>
</main>
</div>
`)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
}
//line views/readers.qtpl:78
func WriteAttachmentMenuHTML(qq422016 qtio422016.Writer, rq *http.Request, h *hyphae.NonEmptyHypha, u *user.User) {
//line views/readers.qtpl:78
//line views/readers.qtpl:83
func WriteAttachmentMenuHTML(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
//line views/readers.qtpl:83
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
StreamAttachmentMenuHTML(qw422016, rq, h, u)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
}
//line views/readers.qtpl:78
func AttachmentMenuHTML(rq *http.Request, h *hyphae.NonEmptyHypha, u *user.User) string {
//line views/readers.qtpl:78
//line views/readers.qtpl:83
func AttachmentMenuHTML(rq *http.Request, h hyphae.Hypha, u *user.User) string {
//line views/readers.qtpl:83
qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:78
//line views/readers.qtpl:83
WriteAttachmentMenuHTML(qb422016, rq, h, u)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
qs422016 := string(qb422016.B)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:78
//line views/readers.qtpl:83
return qs422016
//line views/readers.qtpl:78
//line views/readers.qtpl:83
}
// If `contents` == "", a helpful message is shown instead.
//
// If you rename .prevnext, change the docs too.
//line views/readers.qtpl:83
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:88
func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents string) {
//line views/readers.qtpl:88
qw422016.N().S(`
`)
//line views/readers.qtpl:85
//line views/readers.qtpl:90
siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
u := user.FromRequest(rq)
//line views/readers.qtpl:87
//line views/readers.qtpl:92
qw422016.N().S(`
<div class="layout">
<main class="main-width">
<section id="hypha">
`)
//line views/readers.qtpl:91
//line views/readers.qtpl:96
if u.CanProceed("edit") {
//line views/readers.qtpl:91
//line views/readers.qtpl:96
qw422016.N().S(`
<div class="btn btn_navititle">
<a class="btn__link_navititle" href="/edit/`)
//line views/readers.qtpl:93
//line views/readers.qtpl:98
qw422016.E().S(h.CanonicalName())
//line views/readers.qtpl:93
//line views/readers.qtpl:98
qw422016.N().S(`">`)
//line views/readers.qtpl:93
//line views/readers.qtpl:98
qw422016.E().S(lc.Get("ui.edit_link"))
//line views/readers.qtpl:93
//line views/readers.qtpl:98
qw422016.N().S(`</a>
</div>
`)
//line views/readers.qtpl:95
//line views/readers.qtpl:100
}
//line views/readers.qtpl:95
//line views/readers.qtpl:100
qw422016.N().S(`
`)
//line views/readers.qtpl:97
//line views/readers.qtpl:102
if cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && u.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/") {
//line views/readers.qtpl:97
//line views/readers.qtpl:102
qw422016.N().S(`
<div class="btn btn_navititle">
<a class="btn__link_navititle" href="/logout">`)
//line views/readers.qtpl:99
//line views/readers.qtpl:104
qw422016.E().S(lc.Get("ui.logout_link"))
//line views/readers.qtpl:99
//line views/readers.qtpl:104
qw422016.N().S(`</a>
</div>
`)
//line views/readers.qtpl:101
//line views/readers.qtpl:106
if u.Group == "admin" {
//line views/readers.qtpl:101
//line views/readers.qtpl:106
qw422016.N().S(`
<div class="btn btn_navititle">
<a class="btn__link_navititle" href="/admin">`)
//line views/readers.qtpl:103
//line views/readers.qtpl:108
qw422016.E().S(lc.Get("ui.admin_panel"))
//line views/readers.qtpl:103
//line views/readers.qtpl:108
qw422016.N().S(`<a>
</div>
`)
//line views/readers.qtpl:105
//line views/readers.qtpl:110
}
//line views/readers.qtpl:105
//line views/readers.qtpl:110
qw422016.N().S(`
`)
//line views/readers.qtpl:106
//line views/readers.qtpl:111
}
//line views/readers.qtpl:106
//line views/readers.qtpl:111
qw422016.N().S(`
`)
//line views/readers.qtpl:108
//line views/readers.qtpl:113
qw422016.N().S(NaviTitleHTML(h))
//line views/readers.qtpl:108
//line views/readers.qtpl:113
qw422016.N().S(`
`)
//line views/readers.qtpl:109
//line views/readers.qtpl:114
switch h.(type) {
//line views/readers.qtpl:110
//line views/readers.qtpl:115
case *hyphae.EmptyHypha:
//line views/readers.qtpl:110
//line views/readers.qtpl:115
qw422016.N().S(`
`)
//line views/readers.qtpl:111
//line views/readers.qtpl:116
streamnonExistentHyphaNotice(qw422016, h, u, lc)
//line views/readers.qtpl:111
//line views/readers.qtpl:116
qw422016.N().S(`
`)
//line views/readers.qtpl:112
//line views/readers.qtpl:117
default:
//line views/readers.qtpl:112
//line views/readers.qtpl:117
qw422016.N().S(`
`)
//line views/readers.qtpl:113
//line views/readers.qtpl:118
qw422016.N().S(contents)
//line views/readers.qtpl:113
//line views/readers.qtpl:118
qw422016.N().S(`
`)
//line views/readers.qtpl:114
//line views/readers.qtpl:119
}
//line views/readers.qtpl:114
//line views/readers.qtpl:119
qw422016.N().S(`
</section>
<section class="prevnext">
`)
//line views/readers.qtpl:117
//line views/readers.qtpl:122
if prevHyphaName != "" {
//line views/readers.qtpl:117
//line views/readers.qtpl:122
qw422016.N().S(`
<a class="prevnext__el prevnext__prev" href="/hypha/`)
//line views/readers.qtpl:118
//line views/readers.qtpl:123
qw422016.E().S(prevHyphaName)
//line views/readers.qtpl:118
//line views/readers.qtpl:123
qw422016.N().S(`" rel="prev">← `)
//line views/readers.qtpl:118
//line views/readers.qtpl:123
qw422016.E().S(util.BeautifulName(path.Base(prevHyphaName)))
//line views/readers.qtpl:118
//line views/readers.qtpl:123
qw422016.N().S(`</a>
`)
//line views/readers.qtpl:119
//line views/readers.qtpl:124
}
//line views/readers.qtpl:119
//line views/readers.qtpl:124
qw422016.N().S(`
`)
//line views/readers.qtpl:120
//line views/readers.qtpl:125
if nextHyphaName != "" {
//line views/readers.qtpl:120
//line views/readers.qtpl:125
qw422016.N().S(`
<a class="prevnext__el prevnext__next" href="/hypha/`)
//line views/readers.qtpl:121
//line views/readers.qtpl:126
qw422016.E().S(nextHyphaName)
//line views/readers.qtpl:121
//line views/readers.qtpl:126
qw422016.N().S(`" rel="next">`)
//line views/readers.qtpl:121
//line views/readers.qtpl:126
qw422016.E().S(util.BeautifulName(path.Base(nextHyphaName)))
//line views/readers.qtpl:121
//line views/readers.qtpl:126
qw422016.N().S(` </a>
`)
//line views/readers.qtpl:122
//line views/readers.qtpl:127
}
//line views/readers.qtpl:122
//line views/readers.qtpl:127
qw422016.N().S(`
</section>
`)
//line views/readers.qtpl:124
//line views/readers.qtpl:129
StreamSubhyphaeHTML(qw422016, subhyphae, lc)
//line views/readers.qtpl:124
//line views/readers.qtpl:129
qw422016.N().S(`
<section id="hypha-bottom">
`)
//line views/readers.qtpl:126
//line views/readers.qtpl:131
streamhyphaInfo(qw422016, rq, h)
//line views/readers.qtpl:126
//line views/readers.qtpl:131
qw422016.N().S(`
</section>
</main>
`)
//line views/readers.qtpl:129
//line views/readers.qtpl:134
streamsiblingHyphaeHTML(qw422016, siblings, lc)
//line views/readers.qtpl:129
//line views/readers.qtpl:134
qw422016.N().S(`
</div>
`)
//line views/readers.qtpl:131
streamviewScripts(qw422016)
//line views/readers.qtpl:131
qw422016.N().S(`
`)
//line views/readers.qtpl:132
}
//line views/readers.qtpl:132
func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) {
//line views/readers.qtpl:132
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:132
StreamHyphaHTML(qw422016, rq, lc, h, contents)
//line views/readers.qtpl:132
qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:132
}
//line views/readers.qtpl:132
func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) string {
//line views/readers.qtpl:132
qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:132
WriteHyphaHTML(qb422016, rq, lc, h, contents)
//line views/readers.qtpl:132
qs422016 := string(qb422016.B)
//line views/readers.qtpl:132
qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:132
return qs422016
//line views/readers.qtpl:132
}
//line views/readers.qtpl:134
func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) {
//line views/readers.qtpl:134
qw422016.N().S(`
`)
//line views/readers.qtpl:136
siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName())
streamviewScripts(qw422016)
//line views/readers.qtpl:136
qw422016.N().S(`
`)
//line views/readers.qtpl:137
}
//line views/readers.qtpl:137
func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents string) {
//line views/readers.qtpl:137
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:137
StreamHyphaHTML(qw422016, rq, lc, h, contents)
//line views/readers.qtpl:137
qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:137
}
//line views/readers.qtpl:137
func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents string) string {
//line views/readers.qtpl:137
qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:137
WriteHyphaHTML(qb422016, rq, lc, h, contents)
//line views/readers.qtpl:137
qs422016 := string(qb422016.B)
//line views/readers.qtpl:137
qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:137
return qs422016
//line views/readers.qtpl:137
}
//line views/readers.qtpl:139
func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) {
//line views/readers.qtpl:139
qw422016.N().S(`
`)
//line views/readers.qtpl:141
siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName())
//line views/readers.qtpl:142
qw422016.N().S(`
<div class="layout">
<main class="main-width">
<section>
<p>`)
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.E().S(lc.Get("ui.revision_warning"))
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.N().S(` <a href="/rev-text/`)
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.E().S(revHash)
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.N().S(`/`)
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.E().S(h.CanonicalName())
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.N().S(`">`)
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.E().S(lc.Get("ui.revision_link"))
//line views/readers.qtpl:141
//line views/readers.qtpl:146
qw422016.N().S(`</a></p>
`)
//line views/readers.qtpl:142
//line views/readers.qtpl:147
qw422016.N().S(NaviTitleHTML(h))
//line views/readers.qtpl:142
//line views/readers.qtpl:147
qw422016.N().S(`
`)
//line views/readers.qtpl:143
//line views/readers.qtpl:148
qw422016.N().S(contents)
//line views/readers.qtpl:143
//line views/readers.qtpl:148
qw422016.N().S(`
</section>
`)
//line views/readers.qtpl:145
//line views/readers.qtpl:150
StreamSubhyphaeHTML(qw422016, subhyphae, lc)
//line views/readers.qtpl:145
//line views/readers.qtpl:150
qw422016.N().S(`
</main>
`)
//line views/readers.qtpl:147
//line views/readers.qtpl:152
streamsiblingHyphaeHTML(qw422016, siblings, lc)
//line views/readers.qtpl:147
//line views/readers.qtpl:152
qw422016.N().S(`
</div>
`)
//line views/readers.qtpl:149
//line views/readers.qtpl:154
streamviewScripts(qw422016)
//line views/readers.qtpl:149
//line views/readers.qtpl:154
qw422016.N().S(`
`)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
}
//line views/readers.qtpl:150
func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) {
//line views/readers.qtpl:150
//line views/readers.qtpl:155
func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) {
//line views/readers.qtpl:155
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
StreamRevisionHTML(qw422016, rq, lc, h, contents, revHash)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
}
//line views/readers.qtpl:150
func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) string {
//line views/readers.qtpl:150
//line views/readers.qtpl:155
func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) string {
//line views/readers.qtpl:155
qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:150
//line views/readers.qtpl:155
WriteRevisionHTML(qb422016, rq, lc, h, contents, revHash)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
qs422016 := string(qb422016.B)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:150
//line views/readers.qtpl:155
return qs422016
//line views/readers.qtpl:150
//line views/readers.qtpl:155
}
//line views/readers.qtpl:152
//line views/readers.qtpl:157
func streamviewScripts(qw422016 *qt422016.Writer) {
//line views/readers.qtpl:152
//line views/readers.qtpl:157
qw422016.N().S(`
`)
//line views/readers.qtpl:153
//line views/readers.qtpl:158
for _, scriptPath := range cfg.ViewScripts {
//line views/readers.qtpl:153
//line views/readers.qtpl:158
qw422016.N().S(`
<script src="`)
//line views/readers.qtpl:154
//line views/readers.qtpl:159
qw422016.E().S(scriptPath)
//line views/readers.qtpl:154
//line views/readers.qtpl:159
qw422016.N().S(`"></script>
`)
//line views/readers.qtpl:155
//line views/readers.qtpl:160
}
//line views/readers.qtpl:155
//line views/readers.qtpl:160
qw422016.N().S(`
`)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
}
//line views/readers.qtpl:156
//line views/readers.qtpl:161
func writeviewScripts(qq422016 qtio422016.Writer) {
//line views/readers.qtpl:156
//line views/readers.qtpl:161
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
streamviewScripts(qw422016)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
qt422016.ReleaseWriter(qw422016)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
}
//line views/readers.qtpl:156
//line views/readers.qtpl:161
func viewScripts() string {
//line views/readers.qtpl:156
//line views/readers.qtpl:161
qb422016 := qt422016.AcquireByteBuffer()
//line views/readers.qtpl:156
//line views/readers.qtpl:161
writeviewScripts(qb422016)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
qs422016 := string(qb422016.B)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
qt422016.ReleaseByteBuffer(qb422016)
//line views/readers.qtpl:156
//line views/readers.qtpl:161
return qs422016
//line views/readers.qtpl:156
//line views/readers.qtpl:161
}

View File

@ -262,16 +262,17 @@ sort.Strings(editors)
close(hyphaNames)
%}
{% for hyphaName := range sortedHypha %}
{% code hypha := hyphae.ByName(hyphaName).(*hyphae.NonEmptyHypha) %}
{% code h := hyphae.ByName(hyphaName) %}
<li class="hypha-list__entry">
<a class="hypha-list__link" href="/hypha/{%s hypha.CanonicalName() %}">
{%s util.BeautifulName(hypha.CanonicalName()) %}
<a class="hypha-list__link" href="/hypha/{%s h.CanonicalName() %}">
{%s util.BeautifulName(h.CanonicalName()) %}
</a>
{% if hypha.Kind() == hyphae.HyphaMedia %}
{% switch h := h.(type) %}
{% case *hyphae.MediaHypha %}
<span class="hypha-list__amnt-type">
{%s filepath.Ext(hypha.BinaryPath())[1:] %}
{%s filepath.Ext(h.MediaFilePath())[1:] %}
</span>
{% endif %}
{% endswitch %}
</li>
{% endfor %}
</ul>

View File

@ -1020,247 +1020,249 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
qw422016.N().S(`
`)
//line views/stuff.qtpl:265
hypha := hyphae.ByName(hyphaName).(*hyphae.NonEmptyHypha)
h := hyphae.ByName(hyphaName)
//line views/stuff.qtpl:265
qw422016.N().S(`
<li class="hypha-list__entry">
<a class="hypha-list__link" href="/hypha/`)
//line views/stuff.qtpl:267
qw422016.E().S(hypha.CanonicalName())
qw422016.E().S(h.CanonicalName())
//line views/stuff.qtpl:267
qw422016.N().S(`">
`)
//line views/stuff.qtpl:268
qw422016.E().S(util.BeautifulName(hypha.CanonicalName()))
qw422016.E().S(util.BeautifulName(h.CanonicalName()))
//line views/stuff.qtpl:268
qw422016.N().S(`
</a>
`)
//line views/stuff.qtpl:270
if hypha.Kind() == hyphae.HyphaMedia {
//line views/stuff.qtpl:270
switch h := h.(type) {
//line views/stuff.qtpl:271
case *hyphae.MediaHypha:
//line views/stuff.qtpl:271
qw422016.N().S(`
<span class="hypha-list__amnt-type">
`)
//line views/stuff.qtpl:272
qw422016.E().S(filepath.Ext(hypha.BinaryPath())[1:])
//line views/stuff.qtpl:272
//line views/stuff.qtpl:273
qw422016.E().S(filepath.Ext(h.MediaFilePath())[1:])
//line views/stuff.qtpl:273
qw422016.N().S(`
</span>
`)
//line views/stuff.qtpl:274
//line views/stuff.qtpl:275
}
//line views/stuff.qtpl:274
//line views/stuff.qtpl:275
qw422016.N().S(`
</li>
`)
//line views/stuff.qtpl:276
//line views/stuff.qtpl:277
}
//line views/stuff.qtpl:276
//line views/stuff.qtpl:277
qw422016.N().S(`
</ul>
</main>
</div>
`)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
}
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
func WriteHyphaListHTML(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
StreamHyphaListHTML(qw422016, lc)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
qt422016.ReleaseWriter(qw422016)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
}
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
func HyphaListHTML(lc *l18n.Localizer) string {
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
qb422016 := qt422016.AcquireByteBuffer()
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
WriteHyphaListHTML(qb422016, lc)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
qs422016 := string(qb422016.B)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
qt422016.ReleaseByteBuffer(qb422016)
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
return qs422016
//line views/stuff.qtpl:280
//line views/stuff.qtpl:281
}
//line views/stuff.qtpl:282
//line views/stuff.qtpl:283
func StreamAboutHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
//line views/stuff.qtpl:282
//line views/stuff.qtpl:283
qw422016.N().S(`
<div class="layout">
<main class="main-width">
<section>
<h1>`)
//line views/stuff.qtpl:286
//line views/stuff.qtpl:287
qw422016.E().S(lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName}))
//line views/stuff.qtpl:286
//line views/stuff.qtpl:287
qw422016.N().S(`</h1>
<ul>
<li><b>`)
//line views/stuff.qtpl:288
//line views/stuff.qtpl:289
qw422016.N().S(lc.Get("ui.about_version", &l18n.Replacements{"pre": "<a href=\"https://mycorrhiza.wiki\">", "post": "</a>"}))
//line views/stuff.qtpl:288
//line views/stuff.qtpl:289
qw422016.N().S(`</b> 1.8.0</li>
`)
//line views/stuff.qtpl:289
//line views/stuff.qtpl:290
if cfg.UseAuth {
//line views/stuff.qtpl:289
//line views/stuff.qtpl:290
qw422016.N().S(` <li><b>`)
//line views/stuff.qtpl:290
//line views/stuff.qtpl:291
qw422016.E().S(lc.Get("ui.about_usercount"))
//line views/stuff.qtpl:290
//line views/stuff.qtpl:291
qw422016.N().S(`</b> `)
//line views/stuff.qtpl:290
//line views/stuff.qtpl:291
qw422016.N().DUL(user.Count())
//line views/stuff.qtpl:290
//line views/stuff.qtpl:291
qw422016.N().S(`</li>
<li><b>`)
//line views/stuff.qtpl:291
//line views/stuff.qtpl:292
qw422016.E().S(lc.Get("ui.about_homepage"))
//line views/stuff.qtpl:291
//line views/stuff.qtpl:292
qw422016.N().S(`</b> <a href="/">`)
//line views/stuff.qtpl:291
//line views/stuff.qtpl:292
qw422016.E().S(cfg.HomeHypha)
//line views/stuff.qtpl:291
//line views/stuff.qtpl:292
qw422016.N().S(`</a></li>
<li><b>`)
//line views/stuff.qtpl:292
//line views/stuff.qtpl:293
qw422016.E().S(lc.Get("ui.about_admins"))
//line views/stuff.qtpl:292
//line views/stuff.qtpl:293
qw422016.N().S(`</b>`)
//line views/stuff.qtpl:292
//line views/stuff.qtpl:293
for i, username := range user.ListUsersWithGroup("admin") {
//line views/stuff.qtpl:293
//line views/stuff.qtpl:294
if i > 0 {
//line views/stuff.qtpl:293
//line views/stuff.qtpl:294
qw422016.N().S(`<span aria-hidden="true">, </span>
`)
//line views/stuff.qtpl:294
//line views/stuff.qtpl:295
}
//line views/stuff.qtpl:294
//line views/stuff.qtpl:295
qw422016.N().S(` <a href="/hypha/`)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.E().S(cfg.UserHypha)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.N().S(`/`)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.E().S(username)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.N().S(`">`)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.E().S(username)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.N().S(`</a>`)
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
}
//line views/stuff.qtpl:295
//line views/stuff.qtpl:296
qw422016.N().S(`</li>
`)
//line views/stuff.qtpl:296
//line views/stuff.qtpl:297
} else {
//line views/stuff.qtpl:296
//line views/stuff.qtpl:297
qw422016.N().S(` <li>`)
//line views/stuff.qtpl:297
//line views/stuff.qtpl:298
qw422016.E().S(lc.Get("ui.about_noauth"))
//line views/stuff.qtpl:297
//line views/stuff.qtpl:298
qw422016.N().S(`</li>
`)
//line views/stuff.qtpl:298
//line views/stuff.qtpl:299
}
//line views/stuff.qtpl:298
//line views/stuff.qtpl:299
qw422016.N().S(` </ul>
<p>`)
//line views/stuff.qtpl:300
//line views/stuff.qtpl:301
qw422016.N().S(lc.Get("ui.about_hyphae", &l18n.Replacements{"link": "<a href=\"/list\">/list</a>"}))
//line views/stuff.qtpl:300
//line views/stuff.qtpl:301
qw422016.N().S(`</p>
</section>
</main>
</div>
`)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
}
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
func WriteAboutHTML(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
StreamAboutHTML(qw422016, lc)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
qt422016.ReleaseWriter(qw422016)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
}
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
func AboutHTML(lc *l18n.Localizer) string {
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
qb422016 := qt422016.AcquireByteBuffer()
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
WriteAboutHTML(qb422016, lc)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
qs422016 := string(qb422016.B)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
qt422016.ReleaseByteBuffer(qb422016)
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
return qs422016
//line views/stuff.qtpl:304
//line views/stuff.qtpl:305
}
//line views/stuff.qtpl:306
//line views/stuff.qtpl:307
func StreamCommonScripts(qw422016 *qt422016.Writer) {
//line views/stuff.qtpl:306
//line views/stuff.qtpl:307
qw422016.N().S(`
`)
//line views/stuff.qtpl:307
//line views/stuff.qtpl:308
for _, scriptPath := range cfg.CommonScripts {
//line views/stuff.qtpl:307
//line views/stuff.qtpl:308
qw422016.N().S(`
<script src="`)
//line views/stuff.qtpl:308
//line views/stuff.qtpl:309
qw422016.E().S(scriptPath)
//line views/stuff.qtpl:308
//line views/stuff.qtpl:309
qw422016.N().S(`"></script>
`)
//line views/stuff.qtpl:309
//line views/stuff.qtpl:310
}
//line views/stuff.qtpl:309
//line views/stuff.qtpl:310
qw422016.N().S(`
`)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
}
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
func WriteCommonScripts(qq422016 qtio422016.Writer) {
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
qw422016 := qt422016.AcquireWriter(qq422016)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
StreamCommonScripts(qw422016)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
qt422016.ReleaseWriter(qw422016)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
}
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
func CommonScripts() string {
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
qb422016 := qt422016.AcquireByteBuffer()
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
WriteCommonScripts(qb422016)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
qs422016 := string(qb422016.B)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
qt422016.ReleaseByteBuffer(qb422016)
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
return qs422016
//line views/stuff.qtpl:310
//line views/stuff.qtpl:311
}

View File

@ -37,7 +37,7 @@ func initMutators(r *mux.Router) {
func factoryHandlerAsker(
actionPath string,
asker func(*user.User, hyphae.Hypher, *l18n.Localizer) (string, error),
asker func(*user.User, hyphae.Hypha, *l18n.Localizer) (string, error),
succTitleKey string,
succPageTemplate func(*http.Request, string, bool) string,
) func(http.ResponseWriter, *http.Request) {
@ -63,7 +63,7 @@ func factoryHandlerAsker(
w,
views.BaseHTML(
fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)),
succPageTemplate(rq, hyphaName, func(h hyphae.Hypher) bool {
succPageTemplate(rq, hyphaName, func(h hyphae.Hypha) bool {
switch h.(type) {
case *hyphae.EmptyHypha:
return false
@ -99,7 +99,7 @@ var handlerRenameAsk = factoryHandlerAsker(
func factoryHandlerConfirmer(
actionPath string,
confirmer func(hyphae.Hypher, *user.User, *http.Request) (*history.Op, string),
confirmer func(hyphae.Hypha, *user.User, *http.Request) (*history.Op, string),
) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
@ -121,14 +121,14 @@ func factoryHandlerConfirmer(
var handlerUnattachConfirm = factoryHandlerConfirmer(
"unattach-confirm",
func(h hyphae.Hypher, u *user.User, rq *http.Request) (*history.Op, string) {
func(h hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
return shroom.UnattachHypha(u, h, l18n.FromRequest(rq))
},
)
var handlerDeleteConfirm = factoryHandlerConfirmer(
"delete-confirm",
func(h hyphae.Hypher, u *user.User, rq *http.Request) (*history.Op, string) {
func(h hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
return shroom.DeleteHypha(u, h, l18n.FromRequest(rq))
},
)
@ -177,7 +177,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
case *hyphae.EmptyHypha:
warning = fmt.Sprintf(`<p class="warning warning_new-hypha">%s</p>`, lc.Get("edit.new_hypha"))
default:
textAreaFill, err = shroom.FetchTextPart(h)
textAreaFill, err = shroom.FetchTextFile(h)
if err != nil {
log.Println(err)
httpErr(w, lc, http.StatusInternalServerError, hyphaName,

View File

@ -47,7 +47,7 @@ func handlerAttachment(w http.ResponseWriter, rq *http.Request) {
util.HTTP200Page(w,
views.BaseHTML(
lc.Get("ui.attach_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}),
views.AttachmentMenuHTML(rq, h.(*hyphae.NonEmptyHypha), u),
views.AttachmentMenuHTML(rq, h, u),
lc,
u))
}
@ -63,6 +63,11 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
u = user.FromRequest(rq)
lc = l18n.FromRequest(rq)
)
switch h := h.(type) {
case *hyphae.EmptyHypha:
w.WriteHeader(http.StatusNotFound)
_, _ = io.WriteString(w, "404 not found")
case hyphae.ExistingHypha:
util.HTTP200Page(w,
views.BaseHTML(
lc.Get("ui.diff_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}),
@ -70,6 +75,7 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
lc,
u))
}
}
// handlerRevisionText sends Mycomarkup text of the hypha at the given revision. See also: handlerRevision, handlerText.
//
@ -82,19 +88,30 @@ func handlerRevisionText(w http.ResponseWriter, rq *http.Request) {
revHash = shorterURL[:firstSlashIndex]
hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
h = hyphae.ByName(hyphaName)
textContents, err = history.FileAtRevision(h.TextPartPath(), revHash)
)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
switch h := h.(type) {
case *hyphae.EmptyHypha:
log.Printf(`Hypha %s does not exist`)
w.WriteHeader(http.StatusNotFound)
case hyphae.ExistingHypha:
if !h.HasTextFile() {
log.Printf(`Media hypha %s has no text`)
w.WriteHeader(http.StatusNotFound)
}
var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash)
if err != nil {
w.WriteHeader(http.StatusNotFound)
log.Printf("While serving text of %s at revision %s: %s\n", hyphaName, revHash, err.Error())
_, _ = io.WriteString(w, "Error: "+err.Error())
return
}
log.Printf("Serving text of %s from %s at revision %s\n", hyphaName, h.TextPartPath(), revHash)
log.Printf("Serving text of %s from %s at revision %s\n", hyphaName, h.TextFilePath(), revHash)
w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, textContents)
}
}
// handlerRevision displays a specific revision of the text part the hypha
func handlerRevision(w http.ResponseWriter, rq *http.Request) {
@ -107,13 +124,17 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
h = hyphae.ByName(hyphaName)
contents = fmt.Sprintf(`<p>%s</p>`, lc.Get("ui.revision_no_text"))
textContents, err = history.FileAtRevision(h.TextPartPath(), revHash)
u = user.FromRequest(rq)
)
switch h := h.(type) {
case *hyphae.TextualHypha:
var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash)
if err == nil {
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textContents)
contents = mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))
}
}
page := views.RevisionHTML(
rq,
lc,
@ -139,13 +160,10 @@ func handlerText(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
hyphaName := util.HyphaNameFromRq(rq, "text")
switch h := hyphae.ByName(hyphaName).(type) {
case *hyphae.EmptyHypha:
case *hyphae.NonEmptyHypha:
if h.Kind() == hyphae.HyphaText {
log.Println("Serving", h.TextPartPath())
case *hyphae.TextualHypha:
log.Println("Serving", h.TextFilePath())
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
http.ServeFile(w, rq, h.TextPartPath())
}
http.ServeFile(w, rq, h.TextFilePath())
}
}
@ -155,16 +173,13 @@ func handlerBinary(w http.ResponseWriter, rq *http.Request) {
hyphaName := util.HyphaNameFromRq(rq, "binary")
switch h := hyphae.ByName(hyphaName).(type) {
case *hyphae.EmptyHypha:
default: // TODO: deindent
switch h := h.(*hyphae.NonEmptyHypha); h.Kind() {
case hyphae.HyphaText:
case *hyphae.TextualHypha:
w.WriteHeader(http.StatusNotFound)
log.Printf("Textual hypha %s has no media, cannot serve\n", h.CanonicalName())
default:
log.Println("Serving", h.BinaryPath())
w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.BinaryPath())))
http.ServeFile(w, rq, h.BinaryPath())
}
case *hyphae.MediaHypha:
log.Println("Serving", h.MediaFilePath())
w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.MediaFilePath())))
http.ServeFile(w, rq, h.MediaFilePath())
}
}
@ -189,8 +204,8 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
lc,
u,
openGraph))
case *hyphae.NonEmptyHypha:
fileContentsT, errT := os.ReadFile(h.TextPartPath())
case hyphae.ExistingHypha:
fileContentsT, errT := os.ReadFile(h.TextFilePath())
if errT == nil {
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT))
ctx = mycocontext.WithWebSiteURL(ctx, cfg.URL)
@ -199,7 +214,8 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
contents = mycomarkup.BlocksToHTML(ctx, ast)
openGraph = getOpenGraph()
}
if h.Kind() == hyphae.HyphaMedia {
switch h := h.(type) {
case *hyphae.MediaHypha:
contents = views.AttachmentHTML(h, lc) + contents
}