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.

Add RTL rendering support to Markdown (#24816)

Support RTL content in Markdown:


![image](https://github.com/go-gitea/gitea/assets/115237/dedb1b0c-2f05-40dc-931a-0d9dc81f7c97)

Example document:
https://try.gitea.io/silverwind/symlink-test/src/branch/master/bidi-text.md
Same on GitHub:
https://github.com/silverwind/symlink-test/blob/master/bidi-text.md

`dir=auto` enables a browser heuristic that sets the text direction
automatically. It is the only way to get automatic text direction.

Ref: https://codeberg.org/Codeberg/Community/issues/1021

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

authored by

silverwind
wxiaoguang
and committed by
GitHub
32d9c47e 1698c15c

+23 -5
+1 -1
modules/markup/html.go
··· 630 630 } 631 631 mentionedUsername := mention[1:] 632 632 633 - if processorHelper.IsUsernameMentionable != nil && processorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { 633 + if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { 634 634 replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, mentionedUsername), mention, "mention")) 635 635 node = node.NextSibling.NextSibling 636 636 } else {
+10
modules/markup/markdown/goldmark.go
··· 47 47 tocMode = rc.TOC 48 48 } 49 49 50 + applyElementDir := func(n ast.Node) { 51 + if markup.DefaultProcessorHelper.ElementDir != "" { 52 + n.SetAttributeString("dir", []byte(markup.DefaultProcessorHelper.ElementDir)) 53 + } 54 + } 55 + 50 56 attentionMarkedBlockquotes := make(container.Set[*ast.Blockquote]) 51 57 _ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { 52 58 if !entering { ··· 69 75 header.ID = util.BytesToReadOnlyString(id.([]byte)) 70 76 } 71 77 tocList = append(tocList, header) 78 + applyElementDir(v) 79 + case *ast.Paragraph: 80 + applyElementDir(v) 72 81 case *ast.Image: 73 82 // Images need two things: 74 83 // ··· 171 180 v.AppendChild(v, newChild) 172 181 } 173 182 } 183 + applyElementDir(v) 174 184 case *ast.Text: 175 185 if v.SoftLineBreak() && !v.HardLineBreak() { 176 186 renderMetas := pc.Get(renderMetasKey).(map[string]string)
+4 -2
modules/markup/renderer.go
··· 30 30 31 31 type ProcessorHelper struct { 32 32 IsUsernameMentionable func(ctx context.Context, username string) bool 33 + 34 + ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute 33 35 } 34 36 35 - var processorHelper ProcessorHelper 37 + var DefaultProcessorHelper ProcessorHelper 36 38 37 39 // Init initialize regexps for markdown parsing 38 40 func Init(ph *ProcessorHelper) { 39 41 if ph != nil { 40 - processorHelper = *ph 42 + DefaultProcessorHelper = *ph 41 43 } 42 44 43 45 NewSanitizer()
+1
services/markup/processorhelper.go
··· 13 13 14 14 func ProcessorHelper() *markup.ProcessorHelper { 15 15 return &markup.ProcessorHelper{ 16 + ElementDir: "auto", // set dir="auto" for necessary (eg: <p>, <h?>, etc) tags 16 17 IsUsernameMentionable: func(ctx context.Context, username string) bool { 17 18 mentionedUser, err := user.GetUserByName(ctx, username) 18 19 if err != nil {
+1 -1
tests/integration/user_test.go
··· 250 250 title, _ := rssDoc.ChildrenFiltered("title").Html() 251 251 assert.EqualValues(t, "Feed of &#34;the_1-user.with.all.allowedChars&#34;", title) 252 252 description, _ := rssDoc.ChildrenFiltered("description").Html() 253 - assert.EqualValues(t, "&lt;p&gt;some &lt;a href=&#34;https://commonmark.org/&#34; rel=&#34;nofollow&#34;&gt;commonmark&lt;/a&gt;!&lt;/p&gt;\n", description) 253 + assert.EqualValues(t, "&lt;p dir=&#34;auto&#34;&gt;some &lt;a href=&#34;https://commonmark.org/&#34; rel=&#34;nofollow&#34;&gt;commonmark&lt;/a&gt;!&lt;/p&gt;\n", description) 254 254 } 255 255 } 256 256
+1
web_src/css/base.css
··· 1091 1091 color: var(--color-text); 1092 1092 background: var(--color-box-body); 1093 1093 border-color: var(--color-secondary); 1094 + text-align: start; /* Override fomantic's `text-align: left` to make RTL work via HTML `dir="auto"` */ 1094 1095 } 1095 1096 1096 1097 .ui.table th,
+5 -1
web_src/css/markup/content.css
··· 23 23 } 24 24 25 25 .markup .anchor { 26 + float: left; 26 27 padding-right: 4px; 27 28 margin-left: -20px; 28 - line-height: 1; 29 29 color: inherit; 30 30 } 31 31 ··· 35 35 36 36 .markup .anchor:focus { 37 37 outline: none; 38 + } 39 + 40 + .markup h1 .anchor { 41 + margin-top: -2px; /* re-align to center */ 38 42 } 39 43 40 44 .markup h1 .anchor .svg,