Skip to content

Commit 73e24d1

Browse files
committed
fix markdown render
1 parent cafe05b commit 73e24d1

File tree

16 files changed

+125
-76
lines changed

16 files changed

+125
-76
lines changed

custom/conf/app.example.ini

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,14 +1413,14 @@ LEVEL = Info
14131413
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14141414
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14151415
;;
1416-
;; Render soft line breaks as hard line breaks, which means a single newline character between
1417-
;; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
1418-
;; necessary to force a line break.
1419-
;; Render soft line breaks as hard line breaks for comments
1420-
;ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true
1421-
;;
1422-
;; Render soft line breaks as hard line breaks for markdown documents
1423-
;ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS = false
1416+
;; Customize render options for different contexts. Set to "none" to disable the defaults, or use comma separated list:
1417+
;; * short-issue-pattern: recognized "#123" issue reference and render it as a link to the issue
1418+
;; * new-line-hard-break: render soft line breaks as hard line breaks, which means a single newline character between
1419+
;; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
1420+
;; necessary to force a line break.
1421+
;RENDER_OPTIONS_COMMENT = short-issue-pattern, new-line-hard-break
1422+
;RENDER_OPTIONS_WIKI = short-issue-pattern
1423+
;RENDER_OPTIONS_REPO_FILE =
14241424
;;
14251425
;; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
14261426
;; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
@@ -1435,8 +1435,8 @@ LEVEL = Info
14351435
;; Enables math inline and block detection
14361436
;ENABLE_MATH = true
14371437
;;
1438-
;; Enable delimiters for math code block detection. Set to "none" to disable all, or use comma separated list:
1439-
;; inline-dollar, inline-parentheses, block-dollar, block-square-brackets
1438+
;; Enable delimiters for math code block detection. Set to "none" to disable all,
1439+
;; or use comma separated list: inline-dollar, inline-parentheses, block-dollar, block-square-brackets
14401440
;; Defaults to "inline-dollar,block-dollar" to follow GitHub's behavior.
14411441
;MATH_CODE_BLOCK_DETECTION =
14421442
;;

models/renderhelper/repo_comment.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ func NewRenderContextRepoComment(ctx context.Context, repo *repo_model.Repositor
5656
if repo != nil {
5757
helper.repoLink = repo.Link()
5858
helper.commitChecker = newCommitChecker(ctx, repo)
59-
rctx = rctx.WithMetas(repo.ComposeMetas(ctx))
59+
rctx = rctx.WithMetas(repo.ComposeCommentMetas(ctx))
6060
} else {
6161
// this is almost dead code, only to pass the incorrect tests
6262
helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName)
6363
rctx = rctx.WithMetas(map[string]string{
6464
"user": helper.opts.DeprecatedOwnerName,
6565
"repo": helper.opts.DeprecatedRepoName,
6666

67-
"markdownLineBreakStyle": "comment",
67+
"markdownNewLineHardBreak": "true",
6868
"markupAllowShortIssuePattern": "true",
6969
})
7070
}

models/renderhelper/repo_file.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,13 @@ func NewRenderContextRepoFile(ctx context.Context, repo *repo_model.Repository,
6161
if repo != nil {
6262
helper.repoLink = repo.Link()
6363
helper.commitChecker = newCommitChecker(ctx, repo)
64-
rctx = rctx.WithMetas(repo.ComposeDocumentMetas(ctx))
64+
rctx = rctx.WithMetas(repo.ComposeRepoFileMetas(ctx))
6565
} else {
6666
// this is almost dead code, only to pass the incorrect tests
6767
helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName)
6868
rctx = rctx.WithMetas(map[string]string{
6969
"user": helper.opts.DeprecatedOwnerName,
7070
"repo": helper.opts.DeprecatedRepoName,
71-
72-
"markdownLineBreakStyle": "document",
7371
})
7472
}
7573
rctx = rctx.WithHelper(helper)

models/renderhelper/repo_wiki.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ func NewRenderContextRepoWiki(ctx context.Context, repo *repo_model.Repository,
7070
"user": helper.opts.DeprecatedOwnerName,
7171
"repo": helper.opts.DeprecatedRepoName,
7272

73-
"markdownLineBreakStyle": "document",
7473
"markupAllowShortIssuePattern": "true",
7574
})
7675
}

models/repo/repo.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,15 @@ func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]strin
512512
"repo": repo.Name,
513513
}
514514

515-
unit, err := repo.GetUnit(ctx, unit.TypeExternalTracker)
515+
unitExternalTracker, err := repo.GetUnit(ctx, unit.TypeExternalTracker)
516516
if err == nil {
517-
metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
518-
switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
517+
metas["format"] = unitExternalTracker.ExternalTrackerConfig().ExternalTrackerFormat
518+
switch unitExternalTracker.ExternalTrackerConfig().ExternalTrackerStyle {
519519
case markup.IssueNameStyleAlphanumeric:
520520
metas["style"] = markup.IssueNameStyleAlphanumeric
521521
case markup.IssueNameStyleRegexp:
522522
metas["style"] = markup.IssueNameStyleRegexp
523-
metas["regexp"] = unit.ExternalTrackerConfig().ExternalTrackerRegexpPattern
523+
metas["regexp"] = unitExternalTracker.ExternalTrackerConfig().ExternalTrackerRegexpPattern
524524
default:
525525
metas["style"] = markup.IssueNameStyleNumeric
526526
}
@@ -544,28 +544,29 @@ func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]strin
544544
return repo.commonRenderingMetas
545545
}
546546

547-
// ComposeMetas composes a map of metas for properly rendering comments or comment-like contents (commit message)
548-
func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
547+
// ComposeCommentMetas composes a map of metas for properly rendering comments or comment-like contents (commit message)
548+
func (repo *Repository) ComposeCommentMetas(ctx context.Context) map[string]string {
549549
metas := maps.Clone(repo.composeCommonMetas(ctx))
550-
metas["markdownLineBreakStyle"] = "comment"
551-
metas["markupAllowShortIssuePattern"] = "true"
550+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsComment.NewLineHardBreak)
551+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsComment.ShortIssuePattern)
552552
return metas
553553
}
554554

555555
// ComposeWikiMetas composes a map of metas for properly rendering wikis
556556
func (repo *Repository) ComposeWikiMetas(ctx context.Context) map[string]string {
557557
// does wiki need the "teams" and "org" from common metas?
558558
metas := maps.Clone(repo.composeCommonMetas(ctx))
559-
metas["markdownLineBreakStyle"] = "document"
560-
metas["markupAllowShortIssuePattern"] = "true"
559+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsWiki.NewLineHardBreak)
560+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsWiki.ShortIssuePattern)
561561
return metas
562562
}
563563

564-
// ComposeDocumentMetas composes a map of metas for properly rendering documents (repo files)
565-
func (repo *Repository) ComposeDocumentMetas(ctx context.Context) map[string]string {
564+
// ComposeRepoFileMetas composes a map of metas for properly rendering documents (repo files)
565+
func (repo *Repository) ComposeRepoFileMetas(ctx context.Context) map[string]string {
566566
// does document(file) need the "teams" and "org" from common metas?
567567
metas := maps.Clone(repo.composeCommonMetas(ctx))
568-
metas["markdownLineBreakStyle"] = "document"
568+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsRepoFile.NewLineHardBreak)
569+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsRepoFile.ShortIssuePattern)
569570
return metas
570571
}
571572

models/repo/repo_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func TestMetas(t *testing.T) {
8686

8787
repo.Units = nil
8888

89-
metas := repo.ComposeMetas(db.DefaultContext)
89+
metas := repo.ComposeCommentMetas(db.DefaultContext)
9090
assert.Equal(t, "testRepo", metas["repo"])
9191
assert.Equal(t, "testOwner", metas["user"])
9292

@@ -100,7 +100,7 @@ func TestMetas(t *testing.T) {
100100
testSuccess := func(expectedStyle string) {
101101
repo.Units = []*RepoUnit{&externalTracker}
102102
repo.commonRenderingMetas = nil
103-
metas := repo.ComposeMetas(db.DefaultContext)
103+
metas := repo.ComposeCommentMetas(db.DefaultContext)
104104
assert.Equal(t, expectedStyle, metas["style"])
105105
assert.Equal(t, "testRepo", metas["repo"])
106106
assert.Equal(t, "testOwner", metas["user"])
@@ -121,7 +121,7 @@ func TestMetas(t *testing.T) {
121121
repo, err := GetRepositoryByID(db.DefaultContext, 3)
122122
assert.NoError(t, err)
123123

124-
metas = repo.ComposeMetas(db.DefaultContext)
124+
metas = repo.ComposeCommentMetas(db.DefaultContext)
125125
assert.Contains(t, metas, "org")
126126
assert.Contains(t, metas, "teams")
127127
assert.Equal(t, "org3", metas["org"])

modules/markup/markdown/goldmark.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"code.gitea.io/gitea/modules/container"
1010
"code.gitea.io/gitea/modules/markup"
1111
"code.gitea.io/gitea/modules/markup/internal"
12-
"code.gitea.io/gitea/modules/setting"
1312

1413
"github.com/yuin/goldmark/ast"
1514
east "github.com/yuin/goldmark/extension/ast"
@@ -73,16 +72,8 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
7372
g.transformList(ctx, v, rc)
7473
case *ast.Text:
7574
if v.SoftLineBreak() && !v.HardLineBreak() {
76-
// TODO: this was a quite unclear part, old code: `if metas["mode"] != "document" { use comment link break setting }`
77-
// many places render non-comment contents with no mode=document, then these contents also use comment's hard line break setting
78-
// especially in many tests.
79-
markdownLineBreakStyle := ctx.RenderOptions.Metas["markdownLineBreakStyle"]
80-
switch markdownLineBreakStyle {
81-
case "comment":
82-
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInComments)
83-
case "document":
84-
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
85-
}
75+
newLineHardBreak := ctx.RenderOptions.Metas["markdownNewLineHardBreak"] == "true"
76+
v.SetHardLineBreak(newLineHardBreak)
8677
}
8778
case *ast.CodeSpan:
8879
g.transformCodeSpan(ctx, v, reader)

modules/markup/markdown/markdown_math_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
package markdown
55

66
import (
7-
"code.gitea.io/gitea/modules/setting"
8-
"code.gitea.io/gitea/modules/test"
97
"strings"
108
"testing"
119

1210
"code.gitea.io/gitea/modules/markup"
11+
"code.gitea.io/gitea/modules/setting"
12+
"code.gitea.io/gitea/modules/test"
1313

1414
"github.com/stretchr/testify/assert"
1515
)
@@ -72,7 +72,7 @@ func TestMathRender(t *testing.T) {
7272
},
7373
{
7474
"$$a$$",
75-
`<code class="language-math display">a</code>` + nl,
75+
`<p><code class="language-math">a</code></p>` + nl,
7676
},
7777
{
7878
"$$a$$ test",

modules/markup/render.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"net/url"
11+
"strconv"
1112
"strings"
1213
"time"
1314

@@ -46,7 +47,7 @@ type RenderOptions struct {
4647
// user&repo, format&style&regexp (for external issue pattern), teams&org (for mention)
4748
// RefTypeNameSubURL (for iframe&asciicast)
4849
// markupAllowShortIssuePattern
49-
// markdownLineBreakStyle (comment, document)
50+
// markdownNewLineHardBreak
5051
Metas map[string]string
5152

5253
// used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
@@ -247,7 +248,8 @@ func Init(renderHelpFuncs *RenderHelperFuncs) {
247248
}
248249

249250
func ComposeSimpleDocumentMetas() map[string]string {
250-
return map[string]string{"markdownLineBreakStyle": "document"}
251+
// TODO: there is no separate config option for "simple document" rendering, so temporarily use the same config as "repo file"
252+
return map[string]string{"markdownNewLineHardBreak": strconv.FormatBool(setting.Markdown.RenderOptionsRepoFile.NewLineHardBreak)}
251253
}
252254

253255
type TestRenderHelper struct {

modules/setting/markup.go

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99

1010
"code.gitea.io/gitea/modules/log"
11+
"code.gitea.io/gitea/modules/util"
1112
)
1213

1314
// ExternalMarkupRenderers represents the external markup renderers
@@ -23,6 +24,11 @@ const (
2324
RenderContentModeIframe = "iframe"
2425
)
2526

27+
type MarkdownRenderOptions struct {
28+
NewLineHardBreak bool
29+
ShortIssuePattern bool // Actually it is a "markup" option because it is used in "post processor"
30+
}
31+
2632
type MarkdownMathCodeBlockOptions struct {
2733
ParseInlineDollar bool
2834
ParseInlineParentheses bool
@@ -32,18 +38,19 @@ type MarkdownMathCodeBlockOptions struct {
3238

3339
// Markdown settings
3440
var Markdown = struct {
35-
EnableHardLineBreakInComments bool
36-
EnableHardLineBreakInDocuments bool
37-
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
38-
FileExtensions []string
39-
EnableMath bool
40-
MathCodeBlockDetection []string
41-
MathCodeBlockOptions MarkdownMathCodeBlockOptions `ini:"-"`
41+
RenderOptionsComment MarkdownRenderOptions `ini:"-"`
42+
RenderOptionsWiki MarkdownRenderOptions `ini:"-"`
43+
RenderOptionsRepoFile MarkdownRenderOptions `ini:"-"`
44+
45+
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"` // Actually it is a "markup" option because it is used in "post processor"
46+
FileExtensions []string
47+
48+
EnableMath bool
49+
MathCodeBlockDetection []string
50+
MathCodeBlockOptions MarkdownMathCodeBlockOptions `ini:"-"`
4251
}{
43-
EnableHardLineBreakInComments: true,
44-
EnableHardLineBreakInDocuments: false,
45-
FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd,.livemd", ","),
46-
EnableMath: true,
52+
FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd,.livemd", ","),
53+
EnableMath: true,
4754
}
4855

4956
// MarkupRenderer defines the external parser configured in ini
@@ -69,15 +76,38 @@ type MarkupSanitizerRule struct {
6976

7077
func loadMarkupFrom(rootCfg ConfigProvider) {
7178
mustMapSetting(rootCfg, "markdown", &Markdown)
79+
const none = "none"
80+
81+
const renderOptionShortIssuePattern = "short-issue-pattern"
82+
const renderOptionNewLineHardBreak = "new-line-hard-break"
83+
cfgMarkdown := rootCfg.Section("markdown")
84+
parseMarkdownRenderOptions := func(key string, defaults []string) (ret MarkdownRenderOptions) {
85+
options := cfgMarkdown.Key(key).Strings(",")
86+
options = util.IfEmpty(options, defaults)
87+
for _, opt := range options {
88+
switch opt {
89+
case renderOptionShortIssuePattern:
90+
ret.ShortIssuePattern = true
91+
case renderOptionNewLineHardBreak:
92+
ret.NewLineHardBreak = true
93+
case none:
94+
ret = MarkdownRenderOptions{}
95+
case "":
96+
default:
97+
log.Error("Unknown markdown render option in %s: %s", key, opt)
98+
}
99+
}
100+
return ret
101+
}
102+
Markdown.RenderOptionsComment = parseMarkdownRenderOptions("RENDER_OPTIONS_COMMENT", []string{renderOptionShortIssuePattern, renderOptionNewLineHardBreak})
103+
Markdown.RenderOptionsWiki = parseMarkdownRenderOptions("RENDER_OPTIONS_WIKI", []string{renderOptionShortIssuePattern})
104+
Markdown.RenderOptionsRepoFile = parseMarkdownRenderOptions("RENDER_OPTIONS_REPO_FILE", nil)
72105

73-
const mathCodeNone = "none"
74106
const mathCodeInlineDollar = "inline-dollar"
75107
const mathCodeInlineParentheses = "inline-parentheses"
76108
const mathCodeBlockDollar = "block-dollar"
77109
const mathCodeBlockSquareBrackets = "block-square-brackets"
78-
if len(Markdown.MathCodeBlockDetection) == 0 {
79-
Markdown.MathCodeBlockDetection = []string{mathCodeInlineDollar, mathCodeBlockDollar}
80-
}
110+
Markdown.MathCodeBlockDetection = util.IfEmpty(Markdown.MathCodeBlockDetection, []string{mathCodeInlineDollar, mathCodeBlockDollar})
81111
Markdown.MathCodeBlockOptions = MarkdownMathCodeBlockOptions{}
82112
for _, s := range Markdown.MathCodeBlockDetection {
83113
switch s {
@@ -89,11 +119,11 @@ func loadMarkupFrom(rootCfg ConfigProvider) {
89119
Markdown.MathCodeBlockOptions.ParseBlockDollar = true
90120
case mathCodeBlockSquareBrackets:
91121
Markdown.MathCodeBlockOptions.ParseBlockSquareBrackets = true
92-
case mathCodeNone:
122+
case none:
93123
Markdown.MathCodeBlockOptions = MarkdownMathCodeBlockOptions{}
94124
case "":
95125
default:
96-
log.Fatal("Unknown math code block detection option: " + s)
126+
log.Error("Unknown math code block detection option: %s", s)
97127
}
98128
}
99129

0 commit comments

Comments
 (0)