loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

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

Merge pull request 'Fix some edge cases with permalink rendering' (#3286) from Mai-Lapyst/forgejo:fix-permalink-rendering-edgecases into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3286
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>

+347 -104
+26 -10
modules/markup/file_preview.go
··· 35 35 isTruncated bool 36 36 } 37 37 38 - func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale) *FilePreview { 38 + func NewFilePreviews(ctx *RenderContext, node *html.Node, locale translation.Locale) []*FilePreview { 39 39 if setting.FilePreviewMaxLines == 0 { 40 40 // Feature is disabled 41 41 return nil 42 42 } 43 43 44 - preview := &FilePreview{} 45 - 46 - m := filePreviewPattern.FindStringSubmatchIndex(node.Data) 47 - if m == nil { 44 + mAll := filePreviewPattern.FindAllStringSubmatchIndex(node.Data, -1) 45 + if mAll == nil { 48 46 return nil 49 47 } 50 48 51 - // Ensure that every group has a match 52 - if slices.Contains(m, -1) { 53 - return nil 49 + result := make([]*FilePreview, 0) 50 + 51 + for _, m := range mAll { 52 + if slices.Contains(m, -1) { 53 + continue 54 + } 55 + 56 + preview := newFilePreview(ctx, node, locale, m) 57 + if preview != nil { 58 + result = append(result, preview) 59 + } 54 60 } 55 61 62 + return result 63 + } 64 + 65 + func newFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale, m []int) *FilePreview { 66 + preview := &FilePreview{} 67 + 56 68 urlFull := node.Data[m[0]:m[1]] 57 69 58 70 // Ensure that we only use links to local repositories 59 - if !strings.HasPrefix(urlFull, setting.AppURL+setting.AppSubURL) { 71 + if !strings.HasPrefix(urlFull, setting.AppURL) { 60 72 return nil 61 73 } 62 74 63 - projPath := strings.TrimSuffix(node.Data[m[2]:m[3]], "/") 75 + projPath := strings.TrimPrefix(strings.TrimSuffix(node.Data[m[0]:m[3]], "/"), setting.AppURL) 64 76 65 77 commitSha := node.Data[m[4]:m[5]] 66 78 filePath := node.Data[m[6]:m[7]] ··· 70 82 preview.end = m[1] 71 83 72 84 projPathSegments := strings.Split(projPath, "/") 85 + if len(projPathSegments) != 2 { 86 + return nil 87 + } 88 + 73 89 ownerName := projPathSegments[len(projPathSegments)-2] 74 90 repoName := projPathSegments[len(projPathSegments)-1] 75 91
+34 -26
modules/markup/html.go
··· 1063 1063 return 1064 1064 } 1065 1065 1066 - next := node.NextSibling 1067 - for node != nil && node != next { 1068 - locale := translation.NewLocale("en-US") 1069 - if ctx.Ctx != nil { 1070 - ctxLocale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale) 1071 - if ok { 1072 - locale = ctxLocale 1073 - } 1066 + locale := translation.NewLocale("en-US") 1067 + if ctx.Ctx != nil { 1068 + ctxLocale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale) 1069 + if ok { 1070 + locale = ctxLocale 1074 1071 } 1072 + } 1075 1073 1076 - preview := NewFilePreview(ctx, node, locale) 1077 - if preview == nil { 1078 - return 1074 + next := node.NextSibling 1075 + for node != nil && node != next { 1076 + previews := NewFilePreviews(ctx, node, locale) 1077 + if previews == nil { 1078 + node = node.NextSibling 1079 + continue 1079 1080 } 1080 1081 1081 - previewNode := preview.CreateHTML(locale) 1082 + offset := 0 1083 + for _, preview := range previews { 1084 + previewNode := preview.CreateHTML(locale) 1082 1085 1083 - // Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div 1084 - before := node.Data[:preview.start] 1085 - after := node.Data[preview.end:] 1086 - node.Data = before 1087 - nextSibling := node.NextSibling 1088 - node.Parent.InsertBefore(&html.Node{ 1089 - Type: html.RawNode, 1090 - Data: "</p>", 1091 - }, nextSibling) 1092 - node.Parent.InsertBefore(previewNode, nextSibling) 1093 - node.Parent.InsertBefore(&html.Node{ 1094 - Type: html.RawNode, 1095 - Data: "<p>" + after, 1096 - }, nextSibling) 1086 + // Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div 1087 + before := node.Data[:(preview.start - offset)] 1088 + after := node.Data[(preview.end - offset):] 1089 + afterPrefix := "<p>" 1090 + offset = preview.end - len(afterPrefix) 1091 + node.Data = before 1092 + nextSibling := node.NextSibling 1093 + node.Parent.InsertBefore(&html.Node{ 1094 + Type: html.RawNode, 1095 + Data: "</p>", 1096 + }, nextSibling) 1097 + node.Parent.InsertBefore(previewNode, nextSibling) 1098 + afterNode := &html.Node{ 1099 + Type: html.RawNode, 1100 + Data: afterPrefix + after, 1101 + } 1102 + node.Parent.InsertBefore(afterNode, nextSibling) 1103 + node = afterNode 1104 + } 1097 1105 1098 1106 node = node.NextSibling 1099 1107 }
+287 -68
modules/markup/html_test.go
··· 17 17 "code.gitea.io/gitea/modules/markup" 18 18 "code.gitea.io/gitea/modules/markup/markdown" 19 19 "code.gitea.io/gitea/modules/setting" 20 + "code.gitea.io/gitea/modules/test" 20 21 "code.gitea.io/gitea/modules/translation" 21 22 "code.gitea.io/gitea/modules/util" 22 23 ··· 680 681 } 681 682 682 683 func TestRender_FilePreview(t *testing.T) { 683 - setting.StaticRootPath = "../../" 684 - setting.Names = []string{"english"} 685 - setting.Langs = []string{"en-US"} 684 + defer test.MockVariableValue(&setting.StaticRootPath, "../../")() 685 + defer test.MockVariableValue(&setting.Names, []string{"english"})() 686 + defer test.MockVariableValue(&setting.Langs, []string{"en-US"})() 686 687 translation.InitLocales(context.Background()) 687 688 688 689 setting.AppURL = markup.TestAppURL ··· 705 706 sha := "190d9492934af498c3f669d6a2431dc5459e5b20" 706 707 commitFilePreview := util.URLJoin(markup.TestRepoURL, "src", "commit", sha, "path", "to", "file.go") + "#L2-L3" 707 708 708 - test := func(input, expected string, metas map[string]string) { 709 + testRender := func(input, expected string, metas map[string]string) { 709 710 buffer, err := markup.RenderString(&markup.RenderContext{ 710 711 Ctx: git.DefaultContext, 711 712 RelativePath: ".md", ··· 715 716 assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) 716 717 } 717 718 718 - test( 719 - commitFilePreview, 720 - `<p></p>`+ 721 - `<div class="file-preview-box">`+ 722 - `<div class="header">`+ 723 - `<div>`+ 724 - `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 725 - `</div>`+ 726 - `<span class="text small grey">`+ 727 - `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 728 - `</span>`+ 729 - `</div>`+ 730 - `<div class="ui table">`+ 731 - `<table class="file-preview">`+ 732 - `<tbody>`+ 733 - `<tr>`+ 734 - `<td class="lines-num"><span data-line-number="2"></span></td>`+ 735 - `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 736 - `</tr>`+ 737 - `<tr>`+ 738 - `<td class="lines-num"><span data-line-number="3"></span></td>`+ 739 - `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 740 - `</tr>`+ 741 - `</tbody>`+ 742 - `</table>`+ 743 - `</div>`+ 744 - `</div>`+ 745 - `<p></p>`, 746 - localMetas, 747 - ) 719 + t.Run("single", func(t *testing.T) { 720 + testRender( 721 + commitFilePreview, 722 + `<p></p>`+ 723 + `<div class="file-preview-box">`+ 724 + `<div class="header">`+ 725 + `<div>`+ 726 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 727 + `</div>`+ 728 + `<span class="text small grey">`+ 729 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 730 + `</span>`+ 731 + `</div>`+ 732 + `<div class="ui table">`+ 733 + `<table class="file-preview">`+ 734 + `<tbody>`+ 735 + `<tr>`+ 736 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 737 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 738 + `</tr>`+ 739 + `<tr>`+ 740 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 741 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 742 + `</tr>`+ 743 + `</tbody>`+ 744 + `</table>`+ 745 + `</div>`+ 746 + `</div>`+ 747 + `<p></p>`, 748 + localMetas, 749 + ) 750 + }) 751 + 752 + t.Run("cross-repo", func(t *testing.T) { 753 + testRender( 754 + commitFilePreview, 755 + `<p></p>`+ 756 + `<div class="file-preview-box">`+ 757 + `<div class="header">`+ 758 + `<div>`+ 759 + `<a href="http://localhost:3000/gogits/gogs/" rel="nofollow">gogits/gogs</a> – `+ 760 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 761 + `</div>`+ 762 + `<span class="text small grey">`+ 763 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">gogits/gogs@190d949</a>`+ 764 + `</span>`+ 765 + `</div>`+ 766 + `<div class="ui table">`+ 767 + `<table class="file-preview">`+ 768 + `<tbody>`+ 769 + `<tr>`+ 770 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 771 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 772 + `</tr>`+ 773 + `<tr>`+ 774 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 775 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 776 + `</tr>`+ 777 + `</tbody>`+ 778 + `</table>`+ 779 + `</div>`+ 780 + `</div>`+ 781 + `<p></p>`, 782 + map[string]string{ 783 + "user": "gogits", 784 + "repo": "gogs2", 785 + }, 786 + ) 787 + }) 788 + 789 + t.Run("AppSubURL", func(t *testing.T) { 790 + urlWithSub := util.URLJoin(markup.TestAppURL, "sub", markup.TestOrgRepo, "src", "commit", sha, "path", "to", "file.go") + "#L2-L3" 791 + 792 + testRender( 793 + urlWithSub, 794 + `<p><a href="http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" rel="nofollow"><code>190d949293/path/to/file.go (L2-L3)</code></a></p>`, 795 + localMetas, 796 + ) 797 + 798 + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL+"sub/")() 799 + defer test.MockVariableValue(&setting.AppSubURL, "/sub")() 748 800 749 - test( 750 - commitFilePreview, 751 - `<p></p>`+ 752 - `<div class="file-preview-box">`+ 753 - `<div class="header">`+ 754 - `<div>`+ 755 - `<a href="http://localhost:3000/gogits/gogs/" rel="nofollow">gogits/gogs</a> – `+ 756 - `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 757 - `</div>`+ 758 - `<span class="text small grey">`+ 759 - `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">gogits/gogs@190d949</a>`+ 760 - `</span>`+ 761 - `</div>`+ 762 - `<div class="ui table">`+ 763 - `<table class="file-preview">`+ 764 - `<tbody>`+ 765 - `<tr>`+ 766 - `<td class="lines-num"><span data-line-number="2"></span></td>`+ 767 - `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 768 - `</tr>`+ 769 - `<tr>`+ 770 - `<td class="lines-num"><span data-line-number="3"></span></td>`+ 771 - `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 772 - `</tr>`+ 773 - `</tbody>`+ 774 - `</table>`+ 775 - `</div>`+ 776 - `</div>`+ 777 - `<p></p>`, 778 - map[string]string{ 779 - "user": "gogits", 780 - "repo": "gogs2", 781 - }, 782 - ) 801 + testRender( 802 + urlWithSub, 803 + `<p></p>`+ 804 + `<div class="file-preview-box">`+ 805 + `<div class="header">`+ 806 + `<div>`+ 807 + `<a href="http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 808 + `</div>`+ 809 + `<span class="text small grey">`+ 810 + `Lines 2 to 3 in <a href="http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 811 + `</span>`+ 812 + `</div>`+ 813 + `<div class="ui table">`+ 814 + `<table class="file-preview">`+ 815 + `<tbody>`+ 816 + `<tr>`+ 817 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 818 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 819 + `</tr>`+ 820 + `<tr>`+ 821 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 822 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 823 + `</tr>`+ 824 + `</tbody>`+ 825 + `</table>`+ 826 + `</div>`+ 827 + `</div>`+ 828 + `<p></p>`, 829 + localMetas, 830 + ) 831 + 832 + testRender( 833 + "first without sub "+commitFilePreview+" second "+urlWithSub, 834 + `<p>first without sub <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" rel="nofollow"><code>190d949293/path/to/file.go (L2-L3)</code></a> second </p>`+ 835 + `<div class="file-preview-box">`+ 836 + `<div class="header">`+ 837 + `<div>`+ 838 + `<a href="http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 839 + `</div>`+ 840 + `<span class="text small grey">`+ 841 + `Lines 2 to 3 in <a href="http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 842 + `</span>`+ 843 + `</div>`+ 844 + `<div class="ui table">`+ 845 + `<table class="file-preview">`+ 846 + `<tbody>`+ 847 + `<tr>`+ 848 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 849 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 850 + `</tr>`+ 851 + `<tr>`+ 852 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 853 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 854 + `</tr>`+ 855 + `</tbody>`+ 856 + `</table>`+ 857 + `</div>`+ 858 + `</div>`+ 859 + `<p></p>`, 860 + localMetas, 861 + ) 862 + }) 863 + 864 + t.Run("multiples", func(t *testing.T) { 865 + testRender( 866 + "first "+commitFilePreview+" second "+commitFilePreview, 867 + `<p>first </p>`+ 868 + `<div class="file-preview-box">`+ 869 + `<div class="header">`+ 870 + `<div>`+ 871 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 872 + `</div>`+ 873 + `<span class="text small grey">`+ 874 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 875 + `</span>`+ 876 + `</div>`+ 877 + `<div class="ui table">`+ 878 + `<table class="file-preview">`+ 879 + `<tbody>`+ 880 + `<tr>`+ 881 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 882 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 883 + `</tr>`+ 884 + `<tr>`+ 885 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 886 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 887 + `</tr>`+ 888 + `</tbody>`+ 889 + `</table>`+ 890 + `</div>`+ 891 + `</div>`+ 892 + `<p> second </p>`+ 893 + `<div class="file-preview-box">`+ 894 + `<div class="header">`+ 895 + `<div>`+ 896 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 897 + `</div>`+ 898 + `<span class="text small grey">`+ 899 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 900 + `</span>`+ 901 + `</div>`+ 902 + `<div class="ui table">`+ 903 + `<table class="file-preview">`+ 904 + `<tbody>`+ 905 + `<tr>`+ 906 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 907 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 908 + `</tr>`+ 909 + `<tr>`+ 910 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 911 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 912 + `</tr>`+ 913 + `</tbody>`+ 914 + `</table>`+ 915 + `</div>`+ 916 + `</div>`+ 917 + `<p></p>`, 918 + localMetas, 919 + ) 920 + 921 + testRender( 922 + "first "+commitFilePreview+" second "+commitFilePreview+" third "+commitFilePreview, 923 + `<p>first </p>`+ 924 + `<div class="file-preview-box">`+ 925 + `<div class="header">`+ 926 + `<div>`+ 927 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 928 + `</div>`+ 929 + `<span class="text small grey">`+ 930 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 931 + `</span>`+ 932 + `</div>`+ 933 + `<div class="ui table">`+ 934 + `<table class="file-preview">`+ 935 + `<tbody>`+ 936 + `<tr>`+ 937 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 938 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 939 + `</tr>`+ 940 + `<tr>`+ 941 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 942 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 943 + `</tr>`+ 944 + `</tbody>`+ 945 + `</table>`+ 946 + `</div>`+ 947 + `</div>`+ 948 + `<p> second </p>`+ 949 + `<div class="file-preview-box">`+ 950 + `<div class="header">`+ 951 + `<div>`+ 952 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 953 + `</div>`+ 954 + `<span class="text small grey">`+ 955 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 956 + `</span>`+ 957 + `</div>`+ 958 + `<div class="ui table">`+ 959 + `<table class="file-preview">`+ 960 + `<tbody>`+ 961 + `<tr>`+ 962 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 963 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 964 + `</tr>`+ 965 + `<tr>`+ 966 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 967 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 968 + `</tr>`+ 969 + `</tbody>`+ 970 + `</table>`+ 971 + `</div>`+ 972 + `</div>`+ 973 + `<p> third </p>`+ 974 + `<div class="file-preview-box">`+ 975 + `<div class="header">`+ 976 + `<div>`+ 977 + `<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+ 978 + `</div>`+ 979 + `<span class="text small grey">`+ 980 + `Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+ 981 + `</span>`+ 982 + `</div>`+ 983 + `<div class="ui table">`+ 984 + `<table class="file-preview">`+ 985 + `<tbody>`+ 986 + `<tr>`+ 987 + `<td class="lines-num"><span data-line-number="2"></span></td>`+ 988 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+ 989 + `</tr>`+ 990 + `<tr>`+ 991 + `<td class="lines-num"><span data-line-number="3"></span></td>`+ 992 + `<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+ 993 + `</tr>`+ 994 + `</tbody>`+ 995 + `</table>`+ 996 + `</div>`+ 997 + `</div>`+ 998 + `<p></p>`, 999 + localMetas, 1000 + ) 1001 + }) 783 1002 }