1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-13 22:00:27 +00:00
mycorrhiza/link/link.go
2021-03-02 21:36:57 +05:00

133 lines
3.4 KiB
Go

package link
import (
"fmt"
"path"
"strings"
"github.com/bouncepaw/mycorrhiza/util"
)
// LinkType tells what type the given link is.
type LinkType int
const (
LinkInavild LinkType = iota
// LinkLocalRoot is a link like "/list", "/user-list", etc.
LinkLocalRoot
// LinkLocalHypha is a link like "test", "../test", etc.
LinkLocalHypha
// LinkExternal is an external link with specified protocol.
LinkExternal
// LinkInterwiki is currently unused.
LinkInterwiki
)
// Link is an abstraction for universal representation of links, be they links in mycomarkup links or whatever.
type Link struct {
// Address is what the link points to.
Address string
// Display is what gets nested into the <a> tag.
Display string
Kind LinkType
DestinationUnknown bool
// #...
Anchor string
Protocol string
// How the link address looked originally in source text.
SrcAddress string
// How the link display text looked originally in source text. May be empty.
SrcDisplay string
// RelativeTo is hypha name to which the link is relative to.
RelativeTo string
}
// DoubtExistence sets DestinationUnknown to true if the link is local hypha link.
func (l *Link) DoubtExistence() {
if l.Kind == LinkLocalHypha {
l.DestinationUnknown = true
}
}
// Classes returns CSS class string for given link.
func (l *Link) Classes() string {
if l.Kind == LinkExternal {
return fmt.Sprintf("wikilink wikilink_external wikilink_%s", l.Protocol)
}
classes := "wikilink wikilink_internal"
if l.DestinationUnknown {
classes += " wikilink_new"
}
return classes
}
// Href returns content for the href attrubite for hyperlink. You should always use it.
func (l *Link) Href() string {
switch l.Kind {
case LinkExternal, LinkLocalRoot:
return l.Address
default:
return "/hypha/" + l.Address + l.Anchor
}
}
// ImgSrc returns content for src attribute of img tag. Used with `img{}`.
func (l *Link) ImgSrc() string {
switch l.Kind {
case LinkExternal, LinkLocalRoot:
return l.Address
default:
return "/binary/" + l.Address
}
}
// From returns a Link object given these `address` and `display` on relative to given `hyphaName`.
func From(address, display, hyphaName string) *Link {
address = strings.TrimSpace(address)
link := Link{
SrcAddress: address,
SrcDisplay: display,
RelativeTo: hyphaName,
}
if display == "" {
link.Display = address
} else {
link.Display = strings.TrimSpace(display)
}
switch {
case strings.ContainsRune(address, ':'):
pos := strings.IndexRune(address, ':')
link.Protocol = address[:pos]
link.Kind = LinkExternal
if display == "" {
link.Display = address[pos+1:]
if strings.HasPrefix(link.Display, "//") && len(link.Display) > 2 {
link.Display = link.Display[2:]
}
}
link.Address = address
case strings.HasPrefix(address, "/"):
link.Address = address
link.Kind = LinkLocalRoot
case strings.HasPrefix(address, "./"):
link.Kind = LinkLocalHypha
link.Address = util.CanonicalName(path.Join(hyphaName, address[2:]))
case strings.HasPrefix(address, "../"):
link.Kind = LinkLocalHypha
link.Address = util.CanonicalName(path.Join(path.Dir(hyphaName), address[3:]))
case strings.HasPrefix(address, "#"):
link.Kind = LinkLocalHypha
link.Address = util.CanonicalName(hyphaName)
link.Anchor = address
default:
link.Kind = LinkLocalHypha
link.Address = util.CanonicalName(address)
}
return &link
}