+2
-1
appview/pages/funcmap.go
+2
-1
appview/pages/funcmap.go
···
13
"time"
14
15
"github.com/dustin/go-humanize"
16
)
17
18
func funcMap() template.FuncMap {
···
137
return v.Slice(start, end).Interface()
138
},
139
"markdown": func(text string) template.HTML {
140
-
return template.HTML(renderMarkdown(text))
141
},
142
"isNil": func(t any) bool {
143
// returns false for other "zero" values
···
13
"time"
14
15
"github.com/dustin/go-humanize"
16
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
17
)
18
19
func funcMap() template.FuncMap {
···
138
return v.Slice(start, end).Interface()
139
},
140
"markdown": func(text string) template.HTML {
141
+
return template.HTML(markup.RenderMarkdown(text))
142
},
143
"isNil": func(t any) bool {
144
// returns false for other "zero" values
+3
-2
appview/pages/markdown.go
appview/pages/markup/markdown.go
+3
-2
appview/pages/markdown.go
appview/pages/markup/markdown.go
···
1
+
// Package markup is an umbrella package for all markups and their renderers.
2
+
package markup
3
4
import (
5
"bytes"
···
9
"github.com/yuin/goldmark/parser"
10
)
11
12
+
func RenderMarkdown(source string) string {
13
md := goldmark.New(
14
goldmark.WithExtensions(extension.GFM),
15
goldmark.WithParserOptions(
+26
appview/pages/markup/readme.go
+26
appview/pages/markup/readme.go
···
···
1
+
package markup
2
+
3
+
import "strings"
4
+
5
+
type Format string
6
+
7
+
const (
8
+
FormatMarkdown Format = "markdown"
9
+
FormatText Format = "text"
10
+
)
11
+
12
+
var FileTypes map[Format][]string = map[Format][]string{
13
+
FormatMarkdown: []string{".md", ".markdown", ".mdown", ".mkdn", ".mkd"},
14
+
}
15
+
16
+
func GetFormat(filename string) Format {
17
+
for format, extensions := range FileTypes {
18
+
for _, extension := range extensions {
19
+
if strings.HasSuffix(filename, extension) {
20
+
return format
21
+
}
22
+
}
23
+
}
24
+
// default format
25
+
return FormatText
26
+
}
+15
-5
appview/pages/pages.go
+15
-5
appview/pages/pages.go
···
24
"github.com/microcosm-cc/bluemonday"
25
"tangled.sh/tangled.sh/core/appview/auth"
26
"tangled.sh/tangled.sh/core/appview/db"
27
"tangled.sh/tangled.sh/core/appview/state/userutil"
28
"tangled.sh/tangled.sh/core/types"
29
)
···
350
ext := filepath.Ext(params.ReadmeFileName)
351
switch ext {
352
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
353
-
htmlString = renderMarkdown(params.Readme)
354
params.Raw = false
355
params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString))
356
default:
···
446
}
447
448
type RepoBlobParams struct {
449
-
LoggedInUser *auth.User
450
-
RepoInfo RepoInfo
451
-
Active string
452
-
BreadCrumbs [][]string
453
types.RepoBlobResponse
454
}
455
···
458
b := style.Builder()
459
b.Add(chroma.LiteralString, "noitalic")
460
style, _ = b.Build()
461
462
if params.Lines < 5000 {
463
c := params.Contents
···
24
"github.com/microcosm-cc/bluemonday"
25
"tangled.sh/tangled.sh/core/appview/auth"
26
"tangled.sh/tangled.sh/core/appview/db"
27
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
28
"tangled.sh/tangled.sh/core/appview/state/userutil"
29
"tangled.sh/tangled.sh/core/types"
30
)
···
351
ext := filepath.Ext(params.ReadmeFileName)
352
switch ext {
353
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
354
+
htmlString = markup.RenderMarkdown(params.Readme)
355
params.Raw = false
356
params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString))
357
default:
···
447
}
448
449
type RepoBlobParams struct {
450
+
LoggedInUser *auth.User
451
+
RepoInfo RepoInfo
452
+
Active string
453
+
BreadCrumbs [][]string
454
+
ShowRendered bool
455
+
RenderedContents template.HTML
456
types.RepoBlobResponse
457
}
458
···
461
b := style.Builder()
462
b.Add(chroma.LiteralString, "noitalic")
463
style, _ = b.Build()
464
+
465
+
if params.ShowRendered {
466
+
switch markup.GetFormat(params.Path) {
467
+
case markup.FormatMarkdown:
468
+
params.RenderedContents = template.HTML(markup.RenderMarkdown(params.Contents))
469
+
}
470
+
}
471
472
if params.Lines < 5000 {
473
c := params.Contents
+10
-1
appview/pages/templates/repo/blob.html
+10
-1
appview/pages/templates/repo/blob.html
···
43
<span>{{ byteFmt .SizeHint }}</span>
44
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
45
<a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/raw/{{ .Path }}">view raw</a>
46
</div>
47
</div>
48
</div>
···
52
</p>
53
{{ else }}
54
<div class="overflow-auto relative">
55
-
<div class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
56
</div>
57
{{ end }}
58
{{ end }}
···
43
<span>{{ byteFmt .SizeHint }}</span>
44
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
45
<a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/raw/{{ .Path }}">view raw</a>
46
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
47
+
<a
48
+
href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .ShowRendered }}"
49
+
hx-boost="true"
50
+
>view {{ if .ShowRendered }}code{{ else }}rendered{{ end }}</a>
51
</div>
52
</div>
53
</div>
···
57
</p>
58
{{ else }}
59
<div class="overflow-auto relative">
60
+
{{ if .ShowRendered }}
61
+
<div id="blob-contents" class="prose dark:prose-invert p-6">{{ .RenderedContents }}</div>
62
+
{{ else }}
63
+
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div>
64
+
{{ end }}
65
</div>
66
{{ end }}
67
{{ end }}
+11
appview/state/repo.go
+11
appview/state/repo.go
···
25
"tangled.sh/tangled.sh/core/appview/auth"
26
"tangled.sh/tangled.sh/core/appview/db"
27
"tangled.sh/tangled.sh/core/appview/pages"
28
"tangled.sh/tangled.sh/core/types"
29
30
comatproto "github.com/bluesky-social/indigo/api/atproto"
···
453
}
454
}
455
456
user := s.auth.GetUser(r)
457
s.pages.RepoBlob(w, pages.RepoBlobParams{
458
LoggedInUser: user,
459
RepoInfo: f.RepoInfo(s, user),
460
RepoBlobResponse: result,
461
BreadCrumbs: breadcrumbs,
462
})
463
return
464
}
···
25
"tangled.sh/tangled.sh/core/appview/auth"
26
"tangled.sh/tangled.sh/core/appview/db"
27
"tangled.sh/tangled.sh/core/appview/pages"
28
+
"tangled.sh/tangled.sh/core/appview/pages/markup"
29
"tangled.sh/tangled.sh/core/types"
30
31
comatproto "github.com/bluesky-social/indigo/api/atproto"
···
454
}
455
}
456
457
+
var showRendered = false
458
+
if markup.GetFormat(result.Path) == markup.FormatMarkdown {
459
+
showRendered = true
460
+
}
461
+
462
+
if r.URL.Query().Get("code") == "true" {
463
+
showRendered = false
464
+
}
465
+
466
user := s.auth.GetUser(r)
467
s.pages.RepoBlob(w, pages.RepoBlobParams{
468
LoggedInUser: user,
469
RepoInfo: f.RepoInfo(s, user),
470
RepoBlobResponse: result,
471
BreadCrumbs: breadcrumbs,
472
+
ShowRendered: showRendered,
473
})
474
return
475
}