diff --git a/modules/markup/html.go b/modules/markup/html.go index 11888b853635..da16bcd3cb3f 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -630,7 +630,7 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) { } mentionedUsername := mention[1:] - if processorHelper.IsUsernameMentionable != nil && processorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { + if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) { replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(setting.AppURL, mentionedUsername), mention, "mention")) node = node.NextSibling.NextSibling } else { diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 816e93b700fa..f03a78090035 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -47,6 +47,12 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa tocMode = rc.TOC } + applyElementDir := func(n ast.Node) { + if markup.DefaultProcessorHelper.ElementDir != "" { + n.SetAttributeString("dir", []byte(markup.DefaultProcessorHelper.ElementDir)) + } + } + attentionMarkedBlockquotes := make(container.Set[*ast.Blockquote]) _ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { if !entering { @@ -69,6 +75,9 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa header.ID = util.BytesToReadOnlyString(id.([]byte)) } tocList = append(tocList, header) + applyElementDir(v) + case *ast.Paragraph: + applyElementDir(v) case *ast.Image: // Images need two things: // @@ -171,6 +180,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa v.AppendChild(v, newChild) } } + applyElementDir(v) case *ast.Text: if v.SoftLineBreak() && !v.HardLineBreak() { renderMetas := pc.Get(renderMetasKey).(map[string]string) diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go index f2477f1e9ee9..0331c3742ab1 100644 --- a/modules/markup/renderer.go +++ b/modules/markup/renderer.go @@ -30,14 +30,16 @@ const ( type ProcessorHelper struct { IsUsernameMentionable func(ctx context.Context, username string) bool + + ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute } -var processorHelper ProcessorHelper +var DefaultProcessorHelper ProcessorHelper // Init initialize regexps for markdown parsing func Init(ph *ProcessorHelper) { if ph != nil { - processorHelper = *ph + DefaultProcessorHelper = *ph } NewSanitizer() diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go index 2897f203a90f..3551f85c4668 100644 --- a/services/markup/processorhelper.go +++ b/services/markup/processorhelper.go @@ -13,6 +13,7 @@ import ( func ProcessorHelper() *markup.ProcessorHelper { return &markup.ProcessorHelper{ + ElementDir: "auto", // set dir="auto" for necessary (eg:

, , etc) tags IsUsernameMentionable: func(ctx context.Context, username string) bool { mentionedUser, err := user.GetUserByName(ctx, username) if err != nil { diff --git a/tests/integration/user_test.go b/tests/integration/user_test.go index fa8e6e85c7a3..65cba1dee3e3 100644 --- a/tests/integration/user_test.go +++ b/tests/integration/user_test.go @@ -250,7 +250,7 @@ func TestGetUserRss(t *testing.T) { title, _ := rssDoc.ChildrenFiltered("title").Html() assert.EqualValues(t, "Feed of "the_1-user.with.all.allowedChars"", title) description, _ := rssDoc.ChildrenFiltered("description").Html() - assert.EqualValues(t, "<p>some <a href="https://commonmark.org/" rel="nofollow">commonmark</a>!</p>\n", description) + assert.EqualValues(t, "<p dir="auto">some <a href="https://commonmark.org/" rel="nofollow">commonmark</a>!</p>\n", description) } } diff --git a/web_src/css/base.css b/web_src/css/base.css index 36624ab95762..6c6c5381ad73 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -1091,6 +1091,7 @@ a.label, color: var(--color-text); background: var(--color-box-body); border-color: var(--color-secondary); + text-align: start; /* Override fomantic's `text-align: left` to make RTL work via HTML `dir="auto"` */ } .ui.table th, diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index db67ac4263d2..5b2d6ef2441d 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -23,9 +23,9 @@ } .markup .anchor { + float: left; padding-right: 4px; margin-left: -20px; - line-height: 1; color: inherit; } @@ -37,6 +37,10 @@ outline: none; } +.markup h1 .anchor { + margin-top: -2px; /* re-align to center */ +} + .markup h1 .anchor .svg, .markup h2 .anchor .svg, .markup h3 .anchor .svg,