1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-03-04 02:28:19 +00:00

Auto-detect links

This commit is contained in:
bouncepaw 2021-01-04 02:10:33 +05:00
parent 987dc5b20f
commit bee862563d
4 changed files with 40 additions and 11 deletions

View File

@ -1,8 +1,6 @@
package hyphae package hyphae
import ( import (
"errors"
"github.com/hashicorp/go-memdb" "github.com/hashicorp/go-memdb"
) )
@ -15,8 +13,23 @@ type Hypha struct {
BackLinks []string BackLinks []string
} }
func AddHypha(h Hypha) error { // AddHypha adds a hypha named `name` with such `textPath` and `binaryPath`. Both paths can be empty. Does //not// check for hypha's existence beforehand. Count is handled.
return errors.New("Not implemented") func AddHypha(name, textPath, binaryPath string) {
txn := db.Txn(true)
txn.Insert("hyphae",
&Hypha{
Name: name,
TextPath: textPath,
BinaryPath: binaryPath,
OutLinks: make([]string, 0),
BackLinks: make([]string, 0),
})
txn.Commit()
IncrementCount()
}
// DeleteHypha clears both paths and all out-links from the named hypha and marks it as non-existent. It does not actually delete it from the memdb. Count is handled.
func DeleteHypha(name string) {
} }
// Create the DB schema // Create the DB schema

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"html" "html"
"strings" "strings"
"unicode"
) )
type spanTokenType int type spanTokenType int
@ -34,8 +35,10 @@ func tagFromState(stt spanTokenType, tagState map[spanTokenType]bool, tagName, o
} }
} }
func getLinkNode(input *bytes.Buffer, hyphaName string) string { func getLinkNode(input *bytes.Buffer, hyphaName string, isBracketedLink bool) string {
input.Next(2) if isBracketedLink {
input.Next(2) // drop those [[
}
var ( var (
escaping = false escaping = false
addrBuf = bytes.Buffer{} addrBuf = bytes.Buffer{}
@ -47,11 +50,13 @@ func getLinkNode(input *bytes.Buffer, hyphaName string) string {
if escaping { if escaping {
currBuf.WriteByte(b) currBuf.WriteByte(b)
escaping = false escaping = false
} else if b == '|' && currBuf == &addrBuf { } else if isBracketedLink && b == '|' && currBuf == &addrBuf {
currBuf = &displayBuf currBuf = &displayBuf
} else if b == ']' && bytes.HasPrefix(input.Bytes(), []byte{']'}) { } else if isBracketedLink && b == ']' && bytes.HasPrefix(input.Bytes(), []byte{']'}) {
input.Next(1) input.Next(1)
break break
} else if !isBracketedLink && unicode.IsSpace(rune(b)) {
break
} else { } else {
currBuf.WriteByte(b) currBuf.WriteByte(b)
} }
@ -65,6 +70,12 @@ func getTextNode(input *bytes.Buffer) string {
var ( var (
textNodeBuffer = bytes.Buffer{} textNodeBuffer = bytes.Buffer{}
escaping = false escaping = false
startsWith = func(t string) bool {
return bytes.HasPrefix(input.Bytes(), []byte(t))
}
couldBeLinkStart = func() bool {
return startsWith("https://") || startsWith("http://") || startsWith("gemini://") || startsWith("gopher://") || startsWith("ftp://")
}
) )
// Always read the first byte in advance to avoid endless loops that kill computers (sad experience) // Always read the first byte in advance to avoid endless loops that kill computers (sad experience)
if input.Len() != 0 { if input.Len() != 0 {
@ -82,6 +93,9 @@ func getTextNode(input *bytes.Buffer) string {
} else if strings.IndexByte("/*`^,![~", b) >= 0 { } else if strings.IndexByte("/*`^,![~", b) >= 0 {
input.UnreadByte() input.UnreadByte()
break break
} else if couldBeLinkStart() {
textNodeBuffer.WriteByte(b)
break
} else { } else {
textNodeBuffer.WriteByte(b) textNodeBuffer.WriteByte(b)
} }
@ -132,7 +146,9 @@ func ParagraphToHtml(hyphaName, input string) string {
ret.WriteString(tagFromState(spanMark, tagState, "s", "~~")) ret.WriteString(tagFromState(spanMark, tagState, "s", "~~"))
p.Next(2) p.Next(2)
case startsWith("[["): case startsWith("[["):
ret.WriteString(getLinkNode(p, hyphaName)) ret.WriteString(getLinkNode(p, hyphaName, true))
case startsWith("https://"), startsWith("http://"), startsWith("gemini://"), startsWith("gopher://"), startsWith("ftp://"):
ret.WriteString(getLinkNode(p, hyphaName, false))
default: default:
ret.WriteString(html.EscapeString(getTextNode(p))) ret.WriteString(html.EscapeString(getTextNode(p)))
} }

View File

@ -45,7 +45,7 @@ main h1:not(.navi-title) {font-size:1.7rem;}
blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;} blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;}
.wikilink_new {color:#a55858;} .wikilink_new {color:#a55858;}
.wikilink_new:visited {color:#a55858;} .wikilink_new:visited {color:#a55858;}
.wikilink__destination-type {display: inline; margin-left: .5rem; vertical-align: sub; } .wikilink__destination-type {display: inline; margin: 0 .25rem; vertical-align: sub; }
article code {background-color:#eee; padding: .1rem .3rem; border-radius: .25rem; font-size: 90%; } article code {background-color:#eee; padding: .1rem .3rem; border-radius: .25rem; font-size: 90%; }
article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wrap; border-radius: .25rem;} article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wrap; border-radius: .25rem;}

View File

@ -20,7 +20,7 @@ main h1:not(.navi-title) {font-size:1.7rem;}
blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;} blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;}
.wikilink_new {color:#a55858;} .wikilink_new {color:#a55858;}
.wikilink_new:visited {color:#a55858;} .wikilink_new:visited {color:#a55858;}
.wikilink__destination-type {display: inline; margin-left: .5rem; vertical-align: sub; } .wikilink__destination-type {display: inline; margin: 0 .25rem; vertical-align: sub; }
article code {background-color:#eee; padding: .1rem .3rem; border-radius: .25rem; font-size: 90%; } article code {background-color:#eee; padding: .1rem .3rem; border-radius: .25rem; font-size: 90%; }
article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wrap; border-radius: .25rem;} article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wrap; border-radius: .25rem;}