From 8ac27fc38572f8a7ba35c6a95ca49ec20c07145a Mon Sep 17 00:00:00 2001 From: bouncepaw Date: Tue, 15 Dec 2020 23:59:36 +0500 Subject: [PATCH] Improve links visually --- main.go | 30 ++++ markup/lexer.go | 28 +++- markup/link.go | 9 +- markup/mycomarkup.go | 14 +- templates/asset.qtpl | 18 +++ templates/asset.qtpl.go | 180 +++++++++++++++++++++++- templates/default.css | 6 +- templates/icon/gemini-protocol-icon.svg | 1 + templates/icon/gopher-protocol-icon.svg | 11 ++ templates/icon/http-protocol-icon.svg | 1 + templates/icon/mailto-protocol-icon.svg | 1 + 11 files changed, 287 insertions(+), 12 deletions(-) create mode 100644 templates/icon/gemini-protocol-icon.svg create mode 100644 templates/icon/gopher-protocol-icon.svg create mode 100644 templates/icon/http-protocol-icon.svg create mode 100644 templates/icon/mailto-protocol-icon.svg diff --git a/main.go b/main.go index 1215861..d368bb0 100644 --- a/main.go +++ b/main.go @@ -4,12 +4,14 @@ package main import ( "fmt" + "io/ioutil" "log" "math/rand" "net/http" "os" "path/filepath" "regexp" + "strings" "github.com/bouncepaw/mycorrhiza/history" "github.com/bouncepaw/mycorrhiza/templates" @@ -99,6 +101,33 @@ func handlerStyle(w http.ResponseWriter, rq *http.Request) { } } +func handlerIcon(w http.ResponseWriter, rq *http.Request) { + iconName := strings.TrimPrefix(rq.URL.Path, "/static/icon/") + if iconName == "https" { + iconName = "http" + } + files, err := ioutil.ReadDir(WikiDir + "/static/icon") + if err == nil { + for _, f := range files { + if strings.HasPrefix(f.Name(), iconName+"-protocol-icon") { + http.ServeFile(w, rq, WikiDir+"/static/icon/"+f.Name()) + return + } + } + } + w.Header().Set("Content-Type", "image/svg+xml") + switch iconName { + case "gemini": + w.Write([]byte(templates.IconGemini())) + case "mailto": + w.Write([]byte(templates.IconMailto())) + case "gopher": + w.Write([]byte(templates.IconGopher())) + default: + w.Write([]byte(templates.IconHTTP())) + } +} + func main() { log.Println("Running MycorrhizaWiki β") parseCliArgs() @@ -124,6 +153,7 @@ func main() { http.ServeFile(w, rq, WikiDir+"/static/favicon.ico") }) http.HandleFunc("/static/common.css", handlerStyle) + http.HandleFunc("/static/icon/", handlerIcon) http.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, "/page/"+util.HomePage, http.StatusSeeOther) }) diff --git a/markup/lexer.go b/markup/lexer.go index 08476d6..9ff58f5 100644 --- a/markup/lexer.go +++ b/markup/lexer.go @@ -59,6 +59,9 @@ func geminiLineToAST(line string, state *GemLexerState, ast *[]Line) { addLine(state.buf + "") case "pre": state.buf += "\n" + case "launchpad": + state.where = "" + addLine(state.buf + "") } return } @@ -80,6 +83,8 @@ func geminiLineToAST(line string, state *GemLexerState, ast *[]Line) { goto listState case "number": goto numberState + case "launchpad": + goto launchpadState default: goto normalState } @@ -135,6 +140,23 @@ numberState: } return +launchpadState: + switch { + case startsWith("=>"): + href, text, class := Rocketlink(line, state.name) + state.buf += fmt.Sprintf(`
  • %s
  • `, class, href, text) + case startsWith("```"): + state.where = "pre" + addLine(state.buf + "") + state.id++ + state.buf = fmt.Sprintf("
    ", state.id, strings.TrimPrefix(line, "```"))
    +	default:
    +		state.where = ""
    +		addLine(state.buf + "")
    +		goto normalState
    +	}
    +	return
    +
     normalState:
     	state.id++
     	switch {
    @@ -168,9 +190,9 @@ normalState:
     		addLine(fmt.Sprintf(
     			"
    %s
    ", state.id, remover(">")(line))) case startsWith("=>"): - href, text, class := Rocketlink(line, state.name) - addLine(fmt.Sprintf( - `

    %s

    `, state.id, class, href, text)) + state.where = "launchpad" + state.buf = fmt.Sprintf("
      \n", state.id) + goto launchpadState case startsWith("<="): addLine(parseTransclusion(line, state.name)) diff --git a/markup/link.go b/markup/link.go index eb52c63..ef91e68 100644 --- a/markup/link.go +++ b/markup/link.go @@ -1,6 +1,7 @@ package markup import ( + "fmt" "path" "strings" ) @@ -19,7 +20,13 @@ func LinkParts(addr, display, hyphaName string) (href, text, class string) { switch { case strings.ContainsRune(addr, ':'): - return addr, text, "wikilink_external" + pos := strings.IndexRune(addr, ':') + destination := addr[:pos] + text = addr[pos+1:] + if strings.HasPrefix(text, "//") && len(text) > 2 { + text = text[2:] + } + return addr, text + fmt.Sprintf(``, destination), "wikilink_external" case strings.HasPrefix(addr, "/"): return addr, text, class case strings.HasPrefix(addr, "./"): diff --git a/markup/mycomarkup.go b/markup/mycomarkup.go index fa47e2b..f3fb7a2 100644 --- a/markup/mycomarkup.go +++ b/markup/mycomarkup.go @@ -11,11 +11,6 @@ type MycoDoc struct { // data hyphaName string contents string - - // state - recursionDepth int - - // results } // Constructor @@ -27,10 +22,17 @@ func Doc(hyphaName, contents string) *MycoDoc { } // AsHtml returns an html representation of the document -func (md *MycoDoc) AsHtml() string { +func (md *MycoDoc) AsHTML() string { return "" } +// OpenGraphHTML returns an html representation of og: meta tags. +func (md *MycoDoc) OpenGraphHTML() string { + return "" +} + +/* The rest of this file is currently unused. TODO: use it I guess */ + type BlockType int const ( diff --git a/templates/asset.qtpl b/templates/asset.qtpl index 91e873f..2e6b4f2 100644 --- a/templates/asset.qtpl +++ b/templates/asset.qtpl @@ -1,3 +1,21 @@ {% func DefaultCSS() %} {% cat "default.css" %} {% endfunc %} + +Next three are from https://remixicon.com/ +{% func IconHTTP() %} +{% cat "icon/http-protocol-icon.svg" %} +{% endfunc %} + +{% func IconGemini() %} +{% cat "icon/gemini-protocol-icon.svg" %} +{% endfunc %} + +{% func IconMailto() %} +{% cat "icon/mailto-protocol-icon.svg" %} +{% endfunc %} + +This is a modified version of https://www.svgrepo.com/svg/232085/rat +{% func IconGopher() %} +{% cat "icon/gopher-protocol-icon.svg" %} +{% endfunc %} diff --git a/templates/asset.qtpl.go b/templates/asset.qtpl.go index a90d0ab..dc09918 100644 --- a/templates/asset.qtpl.go +++ b/templates/asset.qtpl.go @@ -45,7 +45,8 @@ main h1:not(.navi-title) {font-size:1.7rem;} blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;} .wikilink_new {color:#a55858;} .wikilink_new:visited {color:#a55858;} -.wikilink_external::after {content:"🌐"; margin-left: .5rem; font-size: small; text-decoration: none; align: bottom;} +.wikilink__destination-type {display: inline; margin-left: .5rem; vertical-align: sub; } + 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;} .codeblock code {padding:0; font-size:15px;} @@ -55,6 +56,9 @@ article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wr .transclusion__link {display: block; text-align: right; font-style: italic; margin-top: .5rem; margin-right: .25rem; color: black; text-decoration: none;} .transclusion__link::before {content: "⇐ ";} +.launchpad { position: relative; list-style: none; } +.launchpad li::before { content: '⇒'; position: absolute; left: 0; } + .binary-container_with-img img, .binary-container_with-video video, .binary-container_with-audio audio {width: 100%} @@ -121,3 +125,177 @@ func DefaultCSS() string { return qs422016 //line templates/asset.qtpl:3 } + +// Next three are from https://remixicon.com/ + +//line templates/asset.qtpl:6 +func StreamIconHTTP(qw422016 *qt422016.Writer) { +//line templates/asset.qtpl:6 + qw422016.N().S(` +`) +//line templates/asset.qtpl:7 + qw422016.N().S(` +`) +//line templates/asset.qtpl:7 + qw422016.N().S(` +`) +//line templates/asset.qtpl:8 +} + +//line templates/asset.qtpl:8 +func WriteIconHTTP(qq422016 qtio422016.Writer) { +//line templates/asset.qtpl:8 + qw422016 := qt422016.AcquireWriter(qq422016) +//line templates/asset.qtpl:8 + StreamIconHTTP(qw422016) +//line templates/asset.qtpl:8 + qt422016.ReleaseWriter(qw422016) +//line templates/asset.qtpl:8 +} + +//line templates/asset.qtpl:8 +func IconHTTP() string { +//line templates/asset.qtpl:8 + qb422016 := qt422016.AcquireByteBuffer() +//line templates/asset.qtpl:8 + WriteIconHTTP(qb422016) +//line templates/asset.qtpl:8 + qs422016 := string(qb422016.B) +//line templates/asset.qtpl:8 + qt422016.ReleaseByteBuffer(qb422016) +//line templates/asset.qtpl:8 + return qs422016 +//line templates/asset.qtpl:8 +} + +//line templates/asset.qtpl:10 +func StreamIconGemini(qw422016 *qt422016.Writer) { +//line templates/asset.qtpl:10 + qw422016.N().S(` +`) +//line templates/asset.qtpl:11 + qw422016.N().S(` +`) +//line templates/asset.qtpl:11 + qw422016.N().S(` +`) +//line templates/asset.qtpl:12 +} + +//line templates/asset.qtpl:12 +func WriteIconGemini(qq422016 qtio422016.Writer) { +//line templates/asset.qtpl:12 + qw422016 := qt422016.AcquireWriter(qq422016) +//line templates/asset.qtpl:12 + StreamIconGemini(qw422016) +//line templates/asset.qtpl:12 + qt422016.ReleaseWriter(qw422016) +//line templates/asset.qtpl:12 +} + +//line templates/asset.qtpl:12 +func IconGemini() string { +//line templates/asset.qtpl:12 + qb422016 := qt422016.AcquireByteBuffer() +//line templates/asset.qtpl:12 + WriteIconGemini(qb422016) +//line templates/asset.qtpl:12 + qs422016 := string(qb422016.B) +//line templates/asset.qtpl:12 + qt422016.ReleaseByteBuffer(qb422016) +//line templates/asset.qtpl:12 + return qs422016 +//line templates/asset.qtpl:12 +} + +//line templates/asset.qtpl:14 +func StreamIconMailto(qw422016 *qt422016.Writer) { +//line templates/asset.qtpl:14 + qw422016.N().S(` +`) +//line templates/asset.qtpl:15 + qw422016.N().S(` +`) +//line templates/asset.qtpl:15 + qw422016.N().S(` +`) +//line templates/asset.qtpl:16 +} + +//line templates/asset.qtpl:16 +func WriteIconMailto(qq422016 qtio422016.Writer) { +//line templates/asset.qtpl:16 + qw422016 := qt422016.AcquireWriter(qq422016) +//line templates/asset.qtpl:16 + StreamIconMailto(qw422016) +//line templates/asset.qtpl:16 + qt422016.ReleaseWriter(qw422016) +//line templates/asset.qtpl:16 +} + +//line templates/asset.qtpl:16 +func IconMailto() string { +//line templates/asset.qtpl:16 + qb422016 := qt422016.AcquireByteBuffer() +//line templates/asset.qtpl:16 + WriteIconMailto(qb422016) +//line templates/asset.qtpl:16 + qs422016 := string(qb422016.B) +//line templates/asset.qtpl:16 + qt422016.ReleaseByteBuffer(qb422016) +//line templates/asset.qtpl:16 + return qs422016 +//line templates/asset.qtpl:16 +} + +// This is a modified version of https://www.svgrepo.com/svg/232085/rat + +//line templates/asset.qtpl:19 +func StreamIconGopher(qw422016 *qt422016.Writer) { +//line templates/asset.qtpl:19 + qw422016.N().S(` +`) +//line templates/asset.qtpl:20 + qw422016.N().S(` + + + +`) +//line templates/asset.qtpl:20 + qw422016.N().S(` +`) +//line templates/asset.qtpl:21 +} + +//line templates/asset.qtpl:21 +func WriteIconGopher(qq422016 qtio422016.Writer) { +//line templates/asset.qtpl:21 + qw422016 := qt422016.AcquireWriter(qq422016) +//line templates/asset.qtpl:21 + StreamIconGopher(qw422016) +//line templates/asset.qtpl:21 + qt422016.ReleaseWriter(qw422016) +//line templates/asset.qtpl:21 +} + +//line templates/asset.qtpl:21 +func IconGopher() string { +//line templates/asset.qtpl:21 + qb422016 := qt422016.AcquireByteBuffer() +//line templates/asset.qtpl:21 + WriteIconGopher(qb422016) +//line templates/asset.qtpl:21 + qs422016 := string(qb422016.B) +//line templates/asset.qtpl:21 + qt422016.ReleaseByteBuffer(qb422016) +//line templates/asset.qtpl:21 + return qs422016 +//line templates/asset.qtpl:21 +} diff --git a/templates/default.css b/templates/default.css index a7c0f07..bc1c814 100644 --- a/templates/default.css +++ b/templates/default.css @@ -20,7 +20,8 @@ main h1:not(.navi-title) {font-size:1.7rem;} blockquote {border-left: 4px black solid; margin-left: 0; padding-left: 1rem;} .wikilink_new {color:#a55858;} .wikilink_new:visited {color:#a55858;} -.wikilink_external::after {content:"🌐"; margin-left: .5rem; font-size: small; text-decoration: none; align: bottom;} +.wikilink__destination-type {display: inline; margin-left: .5rem; vertical-align: sub; } + 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;} .codeblock code {padding:0; font-size:15px;} @@ -30,6 +31,9 @@ article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wr .transclusion__link {display: block; text-align: right; font-style: italic; margin-top: .5rem; margin-right: .25rem; color: black; text-decoration: none;} .transclusion__link::before {content: "⇐ ";} +.launchpad { position: relative; list-style: none; } +.launchpad li::before { content: '⇒'; position: absolute; left: 0; } + .binary-container_with-img img, .binary-container_with-video video, .binary-container_with-audio audio {width: 100%} diff --git a/templates/icon/gemini-protocol-icon.svg b/templates/icon/gemini-protocol-icon.svg new file mode 100644 index 0000000..70beccb --- /dev/null +++ b/templates/icon/gemini-protocol-icon.svg @@ -0,0 +1 @@ + diff --git a/templates/icon/gopher-protocol-icon.svg b/templates/icon/gopher-protocol-icon.svg new file mode 100644 index 0000000..bce1a36 --- /dev/null +++ b/templates/icon/gopher-protocol-icon.svg @@ -0,0 +1,11 @@ + + + + diff --git a/templates/icon/http-protocol-icon.svg b/templates/icon/http-protocol-icon.svg new file mode 100644 index 0000000..d4af44a --- /dev/null +++ b/templates/icon/http-protocol-icon.svg @@ -0,0 +1 @@ + diff --git a/templates/icon/mailto-protocol-icon.svg b/templates/icon/mailto-protocol-icon.svg new file mode 100644 index 0000000..424021c --- /dev/null +++ b/templates/icon/mailto-protocol-icon.svg @@ -0,0 +1 @@ +