Browse Source

Integrated markdown rendering

main
Artemis 2 years ago
parent
commit
f8f9b9ee6c
  1. 2
      README.md
  2. 3
      go.mod
  3. 23
      go.sum
  4. 25
      handlers.go
  5. 56
      static/markdown.css
  6. 12
      templates.go
  7. 23
      templates/markdown.html

2
README.md

@ -1,7 +1,5 @@
# paste
[![Buy me a beer!](https://pix.watch/62tBpX/PURcI2.png)](https://www.buymeacoffee.com/Artemis)
Small temp redis-based pastebin server.
## Table of contents

3
go.mod

@ -4,14 +4,13 @@ require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/go-redis/redis v6.15.2+incompatible
github.com/gorilla/mux v1.7.3
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/prometheus/client_golang v1.2.1
github.com/prometheus/common v0.7.0
github.com/spf13/viper v1.3.2
gitlab.com/Artemix/validator-go v0.0.4
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19
)
go 1.13

23
go.sum

@ -34,6 +34,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
@ -83,7 +84,12 @@ github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLy
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -101,17 +107,31 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
gitlab.com/Artemix/validator-go v0.0.4 h1:RoxCyqa68UvfLOqqrSQ2kQrwkD430RNejYZ4fDcpouk=
gitlab.com/Artemix/validator-go v0.0.4/go.mod h1:fYlTAJFLpA23JxmV3g7hQMIXnnWlRCOOJmTXgbtZIq4=
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 h1:K+bMSIx9A7mLES1rtG+qKduLIXq40DAzYHtb0XuCukA=
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181/go.mod h1:dzYhVIwWCtzPAa4QP98wfB9+mzt33MSmM8wsKiMi2ow=
gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 h1:oYrL81N608MLZhma3ruL8qTM4xcpYECGut8KSxRY59g=
gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19 h1:HsZm6XaTpEgZiZqcXZkUbG6BNtSZE3XyCTfo52YBoDY=
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19/go.mod h1:CRIzp0wh6PvKEAeEOtp9wEpNKJJ1VFTNfHO4+ToRgVA=
gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 h1:qqjvoVXdWIcZCLPMlzgA7P9FZWdPGPvP/l3ef8GzV6o=
gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84/go.mod h1:IJZ+fdMvbW2qW6htJx7sLJ04FEs4Ldl/MDsJtMKywfw=
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI=
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs=
gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638 h1:uPZaMiz6Sz0PZs3IZJWpU5qHKGNy///1pacZC9txiUI=
gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638/go.mod h1:EGRJaqe2eO9XGmFtQCvV3Lm9NLico3UhFwUpCG/+mVU=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -128,6 +148,9 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/nt
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

25
handlers.go

@ -15,11 +15,13 @@ import (
// region Data Structures and types
// Handlers is the base request handlers struct, including dependencies
type Handlers struct {
BackendService storage.Backend
Templates *template.Template
}
// Content is the response data structure
type Content struct {
Error string
Value string
@ -27,17 +29,20 @@ type Content struct {
OriginalCommand PasteSubmitCommand
}
// PasteSubmitCommand is the paste upload command
type PasteSubmitCommand struct {
Paste string
TimeStr string
ExpirationTime time.Duration
}
// PasteSubmitSchema is the schema used to validate form submission
var PasteSubmitSchema = map[string][]validator.Rule{
"paste": {rules.Required{}},
"time": {rules.Required{}, rules.Choice{Choices: []string{"1h", "6h", "12h", "24h"}}},
}
// GenericError is representing generic HTTP errors
type GenericError struct {
Title string
Description string
@ -72,6 +77,7 @@ func (h Handlers) GetRouter() *mux.Router {
// TODO add format filters
r.HandleFunc("/s/{key}", h.handleShowPaste).Methods(http.MethodGet)
r.HandleFunc("/r/{key}", h.handleShowRaw).Methods(http.MethodGet)
r.HandleFunc("/md/{key}", h.HandleShowMarkdown).Methods(http.MethodGet)
return r
}
@ -218,6 +224,25 @@ func (h Handlers) handleShowRaw(w http.ResponseWriter, req *http.Request) {
ErrIf(err)
}
// HandleShowMarkdown renders document with blackfriday.v2 and returns a HTML page
func (h Handlers) HandleShowMarkdown(w http.ResponseWriter, req *http.Request) {
key := mux.Vars(req)["key"]
res, err := h.BackendService.Retrieve(key)
if nil != err {
h.GenericHTTPError(500, err.Error())(w, req)
return
} else if res == "" {
h.GenericHTTPError(404, nil)(w, req)
return
}
ErrIf(h.Templates.ExecuteTemplate(w, "markdown", &Content{
Value: res,
Raw: "/r/" + key,
}))
}
// endregion
// region Error handlers

56
static/markdown.css

@ -0,0 +1,56 @@
/* markdown-renderer-specific style rules */
main {
margin: 2em;
}
@media screen and (min-width: 720px) {
main {
margin: 2em auto;
width: 700px;
}
}
pre > code {
display: block;
}
code {
word-break: break-all;
}
pre {
overflow: auto;
}
h1:before,
h2:before,
h3:before,
h4:before,
h5:before,
h6:before {
content: '';
}
main a {
color: #4299e1;
}
h1 {
font-size: 3rem;
}
h2 {
font-size: 2.25rem;
}
h3 {
font-size: 1.875rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1.125rem;
}

12
templates.go

@ -4,6 +4,8 @@ import (
"fmt"
"html/template"
"strings"
"gitlab.com/golang-commonmark/markdown"
)
// Takes an input string, counts the number of lines,
@ -20,8 +22,16 @@ func Lineno(input string) string {
return output[:len(output)-1]
}
// Markdown allows raw HTML output
func Markdown(input string) template.HTML {
md := markdown.New(markdown.XHTMLOutput(true))
return template.HTML(md.RenderToString([]byte(input)))
}
// InitTemplates parse templates from templates/ folder
func InitTemplates() *template.Template {
return template.Must(template.New("").Funcs(template.FuncMap{
"lineno": Lineno,
"lineno": Lineno,
"markdown": Markdown,
}).ParseGlob("templates/*"))
}

23
templates/markdown.html

@ -0,0 +1,23 @@
{{define "markdown"}}
<!DOCTYPE html>
<html lang="en">
<head>
{{template "header"}}
<link rel="stylesheet" href="/static/markdown.css"/>
</head>
<body>
<header class="bg-gray-200 flex flex-wrap justify-between items-center p-2">
{{template "nav"}}
<fieldset class="shadow-xl rounded bg-white text-black">
<a
href="{{.Raw}}"
class="p-2 bg-blue-400 hover:bg-blue-800 text-white rounded">View raw</a>
</fieldset>
</header>
<main>
{{.Value|markdown}}
</main>
</body>
</html>
{{end}}
Loading…
Cancel
Save