From dd98ae492bfd7701c8a87356c39ff29539dfadcc Mon Sep 17 00:00:00 2001 From: bouncepaw Date: Sun, 31 Jan 2021 00:25:18 +0500 Subject: [PATCH] Start moving universal link-related stuff to a separate module --- link/link.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ markup/link.go | 39 ++++-------------- 2 files changed, 114 insertions(+), 32 deletions(-) create mode 100644 link/link.go diff --git a/link/link.go b/link/link.go new file mode 100644 index 0000000..3f9b9c4 --- /dev/null +++ b/link/link.go @@ -0,0 +1,107 @@ +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 tag. + Display string + Kind LinkType + DestinationUnknown bool + + 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 +} + +// 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. You should always use it. +func (l *Link) Href() string { + switch l.Kind { + case LinkExternal, LinkLocalRoot: + return l.Address + default: + return "/hypha/" + l.Address + } +} + +// From returns a Link object given these `address` and `display` on relative to given `hyphaName`. +func From(address, display, hyphaName string) *Link { + 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:])) + default: + link.Address = util.CanonicalName(address) + } + + return &link +} diff --git a/markup/link.go b/markup/link.go index af3e51c..9243fca 100644 --- a/markup/link.go +++ b/markup/link.go @@ -1,47 +1,22 @@ package markup import ( - "fmt" - "path" "strings" + + "github.com/bouncepaw/mycorrhiza/link" ) // LinkParts determines what href, text and class should resulting have based on mycomarkup's addr, display and hypha name. // // => addr display // [[addr|display]] +// TODO: deprecate func LinkParts(addr, display, hyphaName string) (href, text, class string) { - if display == "" { - text = addr - } else { - text = strings.TrimSpace(display) + l := link.From(addr, display, hyphaName) + if l.Kind == link.LinkLocalHypha && !HyphaExists(l.Address) { + l.DestinationUnknown = true } - class = "wikilink wikilink_internal" - - switch { - case strings.ContainsRune(addr, ':'): - pos := strings.IndexRune(addr, ':') - destination := addr[:pos] - if display == "" { - text = addr[pos+1:] - if strings.HasPrefix(text, "//") && len(text) > 2 { - text = text[2:] - } - } - return addr, text, fmt.Sprintf("wikilink wikilink_external wikilink_%s", destination) - case strings.HasPrefix(addr, "/"): - return addr, text, class - case strings.HasPrefix(addr, "./"): - hyphaName = canonicalName(path.Join(hyphaName, addr[2:])) - case strings.HasPrefix(addr, "../"): - hyphaName = canonicalName(path.Join(path.Dir(hyphaName), addr[3:])) - default: - hyphaName = canonicalName(addr) - } - if !HyphaExists(hyphaName) { - class += " wikilink_new" - } - return "/page/" + hyphaName, text, class + return l.Href(), l.Display, l.Classes() } // Parse markup line starting with "=>" according to wikilink rules.