2021-01-30 19:25:18 +00:00
|
|
|
package link
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/bouncepaw/mycorrhiza/util"
|
|
|
|
)
|
|
|
|
|
|
|
|
// LinkType tells what type the given link is.
|
|
|
|
type LinkType int
|
|
|
|
|
|
|
|
const (
|
2021-03-06 09:44:20 +00:00
|
|
|
LinkInvalid LinkType = iota
|
2021-01-30 19:25:18 +00:00
|
|
|
// 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
|
|
|
|
|
2021-03-02 16:36:57 +00:00
|
|
|
// #...
|
|
|
|
Anchor string
|
2021-01-30 19:25:18 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-01-31 16:39:08 +00:00
|
|
|
// DoubtExistence sets DestinationUnknown to true if the link is local hypha link.
|
|
|
|
func (l *Link) DoubtExistence() {
|
|
|
|
if l.Kind == LinkLocalHypha {
|
|
|
|
l.DestinationUnknown = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-30 19:25:18 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2021-01-31 16:39:08 +00:00
|
|
|
// Href returns content for the href attrubite for hyperlink. You should always use it.
|
2021-01-30 19:25:18 +00:00
|
|
|
func (l *Link) Href() string {
|
|
|
|
switch l.Kind {
|
|
|
|
case LinkExternal, LinkLocalRoot:
|
2021-03-22 14:06:31 +00:00
|
|
|
return l.Address + l.Anchor
|
2021-01-30 19:25:18 +00:00
|
|
|
default:
|
2021-03-02 16:36:57 +00:00
|
|
|
return "/hypha/" + l.Address + l.Anchor
|
2021-01-30 19:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-31 16:39:08 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-30 19:25:18 +00:00
|
|
|
// From returns a Link object given these `address` and `display` on relative to given `hyphaName`.
|
|
|
|
func From(address, display, hyphaName string) *Link {
|
2021-02-06 16:16:21 +00:00
|
|
|
address = strings.TrimSpace(address)
|
2021-01-30 19:25:18 +00:00
|
|
|
link := Link{
|
|
|
|
SrcAddress: address,
|
|
|
|
SrcDisplay: display,
|
|
|
|
RelativeTo: hyphaName,
|
|
|
|
}
|
|
|
|
|
|
|
|
if display == "" {
|
|
|
|
link.Display = address
|
|
|
|
} else {
|
|
|
|
link.Display = strings.TrimSpace(display)
|
|
|
|
}
|
|
|
|
|
2021-03-22 14:06:31 +00:00
|
|
|
if pos := strings.IndexRune(address, '#'); pos != -1 && pos != 0 {
|
2021-03-14 15:10:08 +00:00
|
|
|
link.Anchor = address[pos:]
|
|
|
|
address = address[:pos]
|
|
|
|
}
|
|
|
|
|
2021-01-30 19:25:18 +00:00
|
|
|
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:]
|
|
|
|
}
|
2021-04-19 16:44:32 +00:00
|
|
|
link.Display += link.Anchor
|
2021-01-30 19:25:18 +00:00
|
|
|
}
|
|
|
|
link.Address = address
|
2021-03-22 14:06:31 +00:00
|
|
|
case strings.HasPrefix(address, "#"):
|
|
|
|
link.Kind = LinkLocalHypha
|
|
|
|
link.Address = util.CanonicalName(hyphaName)
|
|
|
|
link.Anchor = address
|
2021-01-30 19:25:18 +00:00
|
|
|
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:]))
|
|
|
|
default:
|
2021-01-31 16:39:08 +00:00
|
|
|
link.Kind = LinkLocalHypha
|
2021-01-30 19:25:18 +00:00
|
|
|
link.Address = util.CanonicalName(address)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &link
|
|
|
|
}
|