appview/pages: rework blob template to work with models.BlobView #793

merged
opened by oppi.li targeting master from push-lqyxyyrozyxs
Changed files
+72 -94
appview
pages
templates
repo
+10 -55
appview/pages/pages.go
··· 744 func (r RepoTreeParams) TreeStats() RepoTreeStats { 745 numFolders, numFiles := 0, 0 746 for _, f := range r.Files { 747 - if !f.IsFile { 748 numFolders += 1 749 - } else if f.IsFile { 750 numFiles += 1 751 } 752 } ··· 817 } 818 819 type RepoBlobParams struct { 820 - LoggedInUser *oauth.User 821 - RepoInfo repoinfo.RepoInfo 822 - Active string 823 - Unsupported bool 824 - IsImage bool 825 - IsVideo bool 826 - ContentSrc string 827 - BreadCrumbs [][]string 828 - ShowRendered bool 829 - RenderToggle bool 830 - RenderedContents template.HTML 831 *tangled.RepoBlob_Output 832 - // Computed fields for template compatibility 833 - Contents string 834 - Lines int 835 - SizeHint uint64 836 - IsBinary bool 837 } 838 839 func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error { 840 - var style *chroma.Style = styles.Get("catpuccin-latte") 841 - 842 - if params.ShowRendered { 843 - switch markup.GetFormat(params.Path) { 844 - case markup.FormatMarkdown: 845 - p.rctx.RepoInfo = params.RepoInfo 846 - p.rctx.RendererType = markup.RendererTypeRepoMarkdown 847 - htmlString := p.rctx.RenderMarkdown(params.Contents) 848 - sanitized := p.rctx.SanitizeDefault(htmlString) 849 - params.RenderedContents = template.HTML(sanitized) 850 - } 851 - } 852 - 853 - c := params.Contents 854 - formatter := chromahtml.New( 855 - chromahtml.InlineCode(false), 856 - chromahtml.WithLineNumbers(true), 857 - chromahtml.WithLinkableLineNumbers(true, "L"), 858 - chromahtml.Standalone(false), 859 - chromahtml.WithClasses(true), 860 - ) 861 - 862 - lexer := lexers.Get(filepath.Base(params.Path)) 863 - if lexer == nil { 864 - lexer = lexers.Fallback 865 - } 866 - 867 - iterator, err := lexer.Tokenise(nil, c) 868 - if err != nil { 869 - return fmt.Errorf("chroma tokenize: %w", err) 870 - } 871 - 872 - var code bytes.Buffer 873 - err = formatter.Format(&code, style, iterator) 874 - if err != nil { 875 - return fmt.Errorf("chroma format: %w", err) 876 } 877 878 - params.Contents = code.String() 879 params.Active = "overview" 880 return p.executeRepo("repo/blob", w, params) 881 }
··· 744 func (r RepoTreeParams) TreeStats() RepoTreeStats { 745 numFolders, numFiles := 0, 0 746 for _, f := range r.Files { 747 + if !f.IsFile() { 748 numFolders += 1 749 + } else if f.IsFile() { 750 numFiles += 1 751 } 752 } ··· 817 } 818 819 type RepoBlobParams struct { 820 + LoggedInUser *oauth.User 821 + RepoInfo repoinfo.RepoInfo 822 + Active string 823 + BreadCrumbs [][]string 824 + BlobView models.BlobView 825 *tangled.RepoBlob_Output 826 } 827 828 func (p *Pages) RepoBlob(w io.Writer, params RepoBlobParams) error { 829 + switch params.BlobView.ContentType { 830 + case models.BlobContentTypeMarkup: 831 + p.rctx.RepoInfo = params.RepoInfo 832 } 833 834 params.Active = "overview" 835 return p.executeRepo("repo/blob", w, params) 836 }
+62 -39
appview/pages/templates/repo/blob.html
··· 11 {{ end }} 12 13 {{ define "repoContent" }} 14 - {{ $lines := split .Contents }} 15 - {{ $tot_lines := len $lines }} 16 - {{ $tot_chars := len (printf "%d" $tot_lines) }} 17 - {{ $code_number_style := "text-gray-400 dark:text-gray-500 left-0 bg-white dark:bg-gray-800 text-right mr-6 select-none inline-block w-12" }} 18 {{ $linkstyle := "no-underline hover:underline" }} 19 <div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700"> 20 <div class="flex flex-col md:flex-row md:justify-between gap-2"> ··· 36 </div> 37 <div id="file-info" class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0"> 38 <span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span> 39 - <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 40 - <span>{{ .Lines }} lines</span> 41 - <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 42 - <span>{{ byteFmt .SizeHint }}</span> 43 - <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 44 - <a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a> 45 - {{ if .RenderToggle }} 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 {{ end }} 52 </div> 53 </div> 54 </div> 55 - {{ if and .IsBinary .Unsupported }} 56 - <p class="text-center text-gray-400 dark:text-gray-500"> 57 - Previews are not supported for this file type. 58 - </p> 59 - {{ else if .IsBinary }} 60 - <div class="text-center"> 61 - {{ if .IsImage }} 62 - <img src="{{ .ContentSrc }}" 63 - alt="{{ .Path }}" 64 - class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" /> 65 - {{ else if .IsVideo }} 66 - <video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded"> 67 - <source src="{{ .ContentSrc }}"> 68 - Your browser does not support the video tag. 69 - </video> 70 - {{ end }} 71 - </div> 72 - {{ else }} 73 - <div class="overflow-auto relative"> 74 - {{ if .ShowRendered }} 75 - <div id="blob-contents" class="prose dark:prose-invert">{{ .RenderedContents }}</div> 76 {{ else }} 77 - <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ $.Contents | escapeHtml }}</div> 78 {{ end }} 79 - </div> 80 {{ end }} 81 {{ template "fragments/multiline-select" }} 82 {{ end }}
··· 11 {{ end }} 12 13 {{ define "repoContent" }} 14 {{ $linkstyle := "no-underline hover:underline" }} 15 <div class="pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700"> 16 <div class="flex flex-col md:flex-row md:justify-between gap-2"> ··· 32 </div> 33 <div id="file-info" class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0"> 34 <span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span> 35 + 36 + {{ if .BlobView.ShowingText }} 37 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 38 + <span>{{ .Lines }} lines</span> 39 + {{ end }} 40 + 41 + {{ if .BlobView.SizeHint }} 42 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 43 + <span>{{ byteFmt .BlobView.SizeHint }}</span> 44 + {{ end }} 45 + 46 + {{ if .BlobView.HasRawView }} 47 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 48 + <a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a> 49 + {{ end }} 50 + 51 + {{ if .BlobView.ShowToggle }} 52 + <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span> 53 + <a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .BlobView.ShowingRendered }}" hx-boost="true"> 54 + view {{ if .BlobView.ShowingRendered }}code{{ else }}rendered{{ end }} 55 + </a> 56 {{ end }} 57 </div> 58 </div> 59 </div> 60 + {{ if .BlobView.IsUnsupported }} 61 + <p class="text-center text-gray-400 dark:text-gray-500"> 62 + Previews are not supported for this file type. 63 + </p> 64 + {{ else if .BlobView.ContentType.IsSubmodule }} 65 + <p class="text-center text-gray-400 dark:text-gray-500"> 66 + This directory is a git submodule of <a href="{{ .BlobView.ContentSrc }}">{{ .BlobView.ContentSrc }}</a>. 67 + </p> 68 + {{ else if .BlobView.ContentType.IsImage }} 69 + <div class="text-center"> 70 + <img src="{{ .BlobView.ContentSrc }}" 71 + alt="{{ .Path }}" 72 + class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" /> 73 + </div> 74 + {{ else if .BlobView.ContentType.IsVideo }} 75 + <div class="text-center"> 76 + <video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded"> 77 + <source src="{{ .BlobView.ContentSrc }}"> 78 + Your browser does not support the video tag. 79 + </video> 80 + </div> 81 + {{ else if .BlobView.ContentType.IsSvg }} 82 + <div class="overflow-auto relative"> 83 + {{ if .BlobView.ShowingRendered }} 84 + <div class="text-center"> 85 + <img src="{{ .BlobView.ContentSrc }}" 86 + alt="{{ .Path }}" 87 + class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" /> 88 + </div> 89 {{ else }} 90 + <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div> 91 {{ end }} 92 + </div> 93 + {{ else if .BlobView.ContentType.IsMarkup }} 94 + <div class="overflow-auto relative"> 95 + {{ if .BlobView.ShowingRendered }} 96 + <div id="blob-contents" class="prose dark:prose-invert">{{ .BlobView.Contents | readme }}</div> 97 + {{ else }} 98 + <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div> 99 + {{ end }} 100 + </div> 101 + {{ else if .BlobView.ContentType.IsCode }} 102 + <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div> 103 {{ end }} 104 {{ template "fragments/multiline-select" }} 105 {{ end }}