forked from tangled.org/core
this repo has no description

appview: pages/blob: toggle render for markdown files

Also sets up a pages/markup package with extensible rendering for future markup languages that we may support.
We may also want an interface or something for markup.RenderMarkdown (maybe just markup.Render), but don't have to bother with that now.

Changed files
+67 -9
appview
pages
state
+2 -1
appview/pages/funcmap.go
···
"time"
"github.com/dustin/go-humanize"
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
)
func funcMap() template.FuncMap {
···
return v.Slice(start, end).Interface()
},
"markdown": func(text string) template.HTML {
-
return template.HTML(renderMarkdown(text))
+
return template.HTML(markup.RenderMarkdown(text))
},
"isNil": func(t any) bool {
// returns false for other "zero" values
+3 -2
appview/pages/markdown.go appview/pages/markup/markdown.go
···
-
package pages
+
// Package markup is an umbrella package for all markups and their renderers.
+
package markup
import (
"bytes"
···
"github.com/yuin/goldmark/parser"
)
-
func renderMarkdown(source string) string {
+
func RenderMarkdown(source string) string {
md := goldmark.New(
goldmark.WithExtensions(extension.GFM),
goldmark.WithParserOptions(
+26
appview/pages/markup/readme.go
···
+
package markup
+
+
import "strings"
+
+
type Format string
+
+
const (
+
FormatMarkdown Format = "markdown"
+
FormatText Format = "text"
+
)
+
+
var FileTypes map[Format][]string = map[Format][]string{
+
FormatMarkdown: []string{".md", ".markdown", ".mdown", ".mkdn", ".mkd"},
+
}
+
+
func GetFormat(filename string) Format {
+
for format, extensions := range FileTypes {
+
for _, extension := range extensions {
+
if strings.HasSuffix(filename, extension) {
+
return format
+
}
+
}
+
}
+
// default format
+
return FormatText
+
}
+15 -5
appview/pages/pages.go
···
"github.com/microcosm-cc/bluemonday"
"tangled.sh/tangled.sh/core/appview/auth"
"tangled.sh/tangled.sh/core/appview/db"
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
"tangled.sh/tangled.sh/core/appview/state/userutil"
"tangled.sh/tangled.sh/core/types"
)
···
ext := filepath.Ext(params.ReadmeFileName)
switch ext {
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
-
htmlString = renderMarkdown(params.Readme)
+
htmlString = markup.RenderMarkdown(params.Readme)
params.Raw = false
params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString))
default:
···
}
type RepoBlobParams struct {
-
LoggedInUser *auth.User
-
RepoInfo RepoInfo
-
Active string
-
BreadCrumbs [][]string
+
LoggedInUser *auth.User
+
RepoInfo RepoInfo
+
Active string
+
BreadCrumbs [][]string
+
ShowRendered bool
+
RenderedContents template.HTML
types.RepoBlobResponse
}
···
b := style.Builder()
b.Add(chroma.LiteralString, "noitalic")
style, _ = b.Build()
+
+
if params.ShowRendered {
+
switch markup.GetFormat(params.Path) {
+
case markup.FormatMarkdown:
+
params.RenderedContents = template.HTML(markup.RenderMarkdown(params.Contents))
+
}
+
}
if params.Lines < 5000 {
c := params.Contents
+10 -1
appview/pages/templates/repo/blob.html
···
<span>{{ byteFmt .SizeHint }}</span>
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/raw/{{ .Path }}">view raw</a>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<a
+
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
+
hx-boost="true"
+
>view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}</a>
</div>
</div>
</div>
···
</p>
{{ else }}
<div class="overflow-auto relative">
-
<div class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
+
{{ if .ShowRendered }}
+
<div id="blob-contents" class="prose dark:prose-invert p-6">{{ .RenderedContents }}</div>
+
{{ else }}
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
+
{{ end }}
</div>
{{ end }}
{{ end }}
+11
appview/state/repo.go
···
"tangled.sh/tangled.sh/core/appview/auth"
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/pages"
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
"tangled.sh/tangled.sh/core/types"
comatproto "github.com/bluesky-social/indigo/api/atproto"
···
}
}
+
var showRendered = false
+
if markup.GetFormat(result.Path) == markup.FormatMarkdown {
+
showRendered = true
+
}
+
+
if r.URL.Query().Get("code") == "true" {
+
showRendered = false
+
}
+
user := s.auth.GetUser(r)
s.pages.RepoBlob(w, pages.RepoBlobParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(s, user),
RepoBlobResponse: result,
BreadCrumbs: breadcrumbs,
+
ShowRendered: showRendered,
})
return
}