Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview,knotserver: pass along a readme candidate in repo.tree responses

this simplifies readme detection and improves page performance.

Signed-off-by: oppiliappan <me@oppi.li>

+102 -45
api/tangled/repotree.go

This is a binary file and will not be displayed.

+15 -17
appview/pages/markup/format.go
··· 1 1 package markup 2 2 3 - import "strings" 3 + import ( 4 + "regexp" 5 + ) 4 6 5 7 type Format string 6 8 ··· 12 10 ) 13 11 14 12 var FileTypes map[Format][]string = map[Format][]string{ 15 - FormatMarkdown: []string{".md", ".markdown", ".mdown", ".mkdn", ".mkd"}, 13 + FormatMarkdown: {".md", ".markdown", ".mdown", ".mkdn", ".mkd"}, 16 14 } 17 15 18 - // ReadmeFilenames contains the list of common README filenames to search for, 19 - // in order of preference. Only includes well-supported formats. 20 - var ReadmeFilenames = []string{ 21 - "README.md", "readme.md", 22 - "README", 23 - "readme", 24 - "README.markdown", 25 - "readme.markdown", 26 - "README.txt", 27 - "readme.txt", 16 + var FileTypePatterns = map[Format]*regexp.Regexp{ 17 + FormatMarkdown: regexp.MustCompile(`(?i)\.(md|markdown|mdown|mkdn|mkd)$`), 18 + } 19 + 20 + var ReadmePattern = regexp.MustCompile(`(?i)^readme(\.(md|markdown|txt))?$`) 21 + 22 + func IsReadmeFile(filename string) bool { 23 + return ReadmePattern.MatchString(filename) 28 24 } 29 25 30 26 func GetFormat(filename string) Format { 31 - for format, extensions := range FileTypes { 32 - for _, extension := range extensions { 33 - if strings.HasSuffix(filename, extension) { 34 - return format 35 - } 27 + for format, pattern := range FileTypePatterns { 28 + if pattern.MatchString(filename) { 29 + return format 36 30 } 37 31 } 38 32 // default format
+20
appview/pages/pages.go
··· 714 714 Active string 715 715 BreadCrumbs [][]string 716 716 TreePath string 717 + Raw bool 718 + HTMLReadme template.HTML 717 719 types.RepoTreeResponse 718 720 } 719 721 ··· 742 740 743 741 func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error { 744 742 params.Active = "overview" 743 + 744 + p.rctx.RepoInfo = params.RepoInfo 745 + p.rctx.RepoInfo.Ref = params.Ref 746 + p.rctx.RendererType = markup.RendererTypeRepoMarkdown 747 + 748 + if params.ReadmeFileName != "" { 749 + ext := filepath.Ext(params.ReadmeFileName) 750 + switch ext { 751 + case ".md", ".markdown", ".mdown", ".mkdn", ".mkd": 752 + params.Raw = false 753 + htmlString := p.rctx.RenderMarkdown(params.Readme) 754 + sanitized := p.rctx.SanitizeDefault(htmlString) 755 + params.HTMLReadme = template.HTML(sanitized) 756 + default: 757 + params.Raw = true 758 + } 759 + } 760 + 745 761 return p.executeRepo("repo/tree", w, params) 746 762 } 747 763
+2 -2
appview/pages/templates/repo/fragments/readme.html
··· 1 1 {{ define "repo/fragments/readme" }} 2 2 <div class="mt-4 rounded bg-white dark:bg-gray-800 drop-shadow-sm w-full mx-auto overflow-hidden"> 3 3 {{- if .ReadmeFileName -}} 4 - <div class="px-4 py-2 bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600 flex items-center gap-2"> 4 + <div class="px-4 py-2 border-b border-gray-200 dark:border-gray-600 flex items-center gap-2"> 5 5 {{ i "file-text" "w-4 h-4" "text-gray-600 dark:text-gray-400" }} 6 6 <span class="font-mono text-sm text-gray-800 dark:text-gray-200">{{ .ReadmeFileName }}</span> 7 7 </div> 8 8 {{- end -}} 9 9 <section 10 - class="p-6 overflow-auto {{ if not .Raw }} 10 + class="px-6 pb-6 overflow-auto {{ if not .Raw }} 11 11 prose dark:prose-invert dark:[&_pre]:bg-gray-900 12 12 dark:[&_code]:text-gray-300 dark:[&_pre_code]:bg-gray-900 13 13 dark:[&_pre]:border dark:[&_pre]:border-gray-700
+6
appview/pages/templates/repo/tree.html
··· 88 88 </div> 89 89 </main> 90 90 {{end}} 91 + 92 + {{ define "repoAfter" }} 93 + {{- if or .HTMLReadme .Readme -}} 94 + {{ template "repo/fragments/readme" . }} 95 + {{- end -}} 96 + {{ end }}
+5 -21
appview/repo/index.go
··· 22 22 "tangled.org/core/appview/db" 23 23 "tangled.org/core/appview/models" 24 24 "tangled.org/core/appview/pages" 25 - "tangled.org/core/appview/pages/markup" 26 25 "tangled.org/core/appview/reporesolver" 27 26 "tangled.org/core/appview/xrpcclient" 28 27 "tangled.org/core/types" ··· 327 328 } 328 329 }() 329 330 330 - // readme content 331 - wg.Add(1) 332 - go func() { 333 - defer wg.Done() 334 - for _, filename := range markup.ReadmeFilenames { 335 - blobResp, err := tangled.RepoBlob(ctx, xrpcc, filename, false, ref, repo) 336 - if err != nil { 337 - continue 338 - } 339 - 340 - if blobResp == nil { 341 - continue 342 - } 343 - 344 - readmeContent = blobResp.Content 345 - readmeFileName = filename 346 - break 347 - } 348 - }() 349 - 350 331 wg.Wait() 351 332 352 333 if errs != nil { ··· 353 374 } 354 375 files = append(files, niceFile) 355 376 } 377 + } 378 + 379 + if treeResp != nil && treeResp.Readme != nil { 380 + readmeFileName = treeResp.Readme.Filename 381 + readmeContent = treeResp.Readme.Contents 356 382 } 357 383 358 384 result := &types.RepoIndexResponse{
+4
appview/repo/repo.go
··· 484 484 if xrpcResp.Dotdot != nil { 485 485 result.DotDot = *xrpcResp.Dotdot 486 486 } 487 + if xrpcResp.Readme != nil { 488 + result.ReadmeFileName = xrpcResp.Readme.Filename 489 + result.Readme = xrpcResp.Readme.Contents 490 + } 487 491 488 492 // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, 489 493 // so we can safely redirect to the "parent" (which is the same file).
+24
knotserver/xrpc/repo_tree.go
··· 4 4 "net/http" 5 5 "path/filepath" 6 6 "time" 7 + "unicode/utf8" 7 8 8 9 "tangled.org/core/api/tangled" 10 + "tangled.org/core/appview/pages/markup" 9 11 "tangled.org/core/knotserver/git" 10 12 xrpcerr "tangled.org/core/xrpc/errors" 11 13 ) ··· 43 41 xrpcerr.WithMessage("failed to read repository tree"), 44 42 ), http.StatusNotFound) 45 43 return 44 + } 45 + 46 + // if any of these files are a readme candidate, pass along its blob contents too 47 + var readmeFileName string 48 + var readmeContents string 49 + for _, file := range files { 50 + if markup.IsReadmeFile(file.Name) { 51 + contents, err := gr.RawContent(filepath.Join(path, file.Name)) 52 + if err != nil { 53 + x.Logger.Error("failed to read contents of file", "path", path, "file", file.Name) 54 + } 55 + 56 + if utf8.Valid(contents) { 57 + readmeFileName = file.Name 58 + readmeContents = string(contents) 59 + break 60 + } 61 + } 46 62 } 47 63 48 64 // convert NiceTree -> tangled.RepoTree_TreeEntry ··· 103 83 Parent: parentPtr, 104 84 Dotdot: dotdotPtr, 105 85 Files: treeEntries, 86 + Readme: &tangled.RepoTree_Readme{ 87 + Filename: readmeFileName, 88 + Contents: readmeContents, 89 + }, 106 90 } 107 91 108 92 writeJson(w, response)
+19
lexicons/repo/tree.json
··· 41 41 "type": "string", 42 42 "description": "Parent directory path" 43 43 }, 44 + "readme": { 45 + "type": "ref", 46 + "ref": "#readme", 47 + "description": "Readme for this file tree" 48 + }, 44 49 "files": { 45 50 "type": "array", 46 51 "items": { ··· 74 69 "description": "Invalid request parameters" 75 70 } 76 71 ] 72 + }, 73 + "readme": { 74 + "type": "object", 75 + "required": ["filename", "contents"], 76 + "properties": { 77 + "filename": { 78 + "type": "string", 79 + "description": "Name of the readme file" 80 + }, 81 + "contents": { 82 + "type": "string", 83 + "description": "Contents of the readme file" 84 + } 85 + } 77 86 }, 78 87 "treeEntry": { 79 88 "type": "object",
+7 -5
types/repo.go
··· 41 41 } 42 42 43 43 type RepoTreeResponse struct { 44 - Ref string `json:"ref,omitempty"` 45 - Parent string `json:"parent,omitempty"` 46 - Description string `json:"description,omitempty"` 47 - DotDot string `json:"dotdot,omitempty"` 48 - Files []NiceTree `json:"files,omitempty"` 44 + Ref string `json:"ref,omitempty"` 45 + Parent string `json:"parent,omitempty"` 46 + Description string `json:"description,omitempty"` 47 + DotDot string `json:"dotdot,omitempty"` 48 + Files []NiceTree `json:"files,omitempty"` 49 + ReadmeFileName string `json:"readme_filename,omitempty"` 50 + Readme string `json:"readme_contents,omitempty"` 49 51 } 50 52 51 53 type TagReference struct {