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.