From 543af2bbe7545eac22bf47fd182d8c295a3e7831 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Mon, 7 Nov 2022 20:29:21 +0000 Subject: [PATCH 01/10] Add attention blocks within quote blocks for `Note` and `Warning` Signed-off-by: Yarden Shoham --- modules/markup/markdown/ast.go | 34 +++++++++++++++++++++++++++ modules/markup/markdown/goldmark.go | 36 +++++++++++++++++++++++++++++ modules/markup/sanitizer.go | 6 +++++ web_src/less/_base.less | 14 +++++++++++ 4 files changed, 90 insertions(+) diff --git a/modules/markup/markdown/ast.go b/modules/markup/markdown/ast.go index c82d5e5e73396..420aef8b5a599 100644 --- a/modules/markup/markdown/ast.go +++ b/modules/markup/markdown/ast.go @@ -180,3 +180,37 @@ func IsColorPreview(node ast.Node) bool { _, ok := node.(*ColorPreview) return ok } + +const ( + AttentionNote string = "note" + AttentionWarning string = "warning" +) + +// Attention is an inline for a color preview +type Attention struct { + ast.BaseInline + AttentionType string +} + +// Dump implements Node.Dump. +func (n *Attention) Dump(source []byte, level int) { + m := map[string]string{} + m["AttentionType"] = n.AttentionType + ast.DumpHelper(n, source, level, m, nil) +} + +// KindAttention is the NodeKind for Attention +var KindAttention = ast.NewNodeKind("Attention") + +// Kind implements Node.Kind. +func (n *Attention) Kind() ast.NodeKind { + return KindAttention +} + +// NewAttention returns a new Attention node. +func NewAttention(attentionType string) *Attention { + return &Attention{ + BaseInline: ast.BaseInline{}, + AttentionType: attentionType, + } +} diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 1a36681366193..d95eb3b44f5c7 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -28,6 +28,8 @@ import ( var byteMailto = []byte("mailto:") +const hasThisBlockquoteBeenAttentionMarked = "has-this-blockquote-been-attention-marked" + // ASTTransformer is a default transformer of the goldmark tree. type ASTTransformer struct{} @@ -184,6 +186,18 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa if css.ColorHandler(strings.ToLower(string(colorContent))) { v.AppendChild(v, NewColorPreview(colorContent)) } + case *ast.Emphasis: + grandparent := n.Parent().Parent() + _, isInBlockquote := grandparent.(*ast.Blockquote) + _, blockquoteAlreadyAttentionMarked := grandparent.AttributeString(hasThisBlockquoteBeenAttentionMarked) + if !blockquoteAlreadyAttentionMarked && isInBlockquote { + fullText := strings.ToLower(string(n.Text(reader.Source()))) + if fullText == AttentionNote || fullText == AttentionWarning { + v.SetAttributeString("class", []byte("attention-"+fullText)) + v.Parent().InsertBefore(v.Parent(), v, NewAttention(fullText)) + grandparent.SetAttributeString(hasThisBlockquoteBeenAttentionMarked, []byte("yes")) + } + } } return ast.WalkContinue, nil }) @@ -273,6 +287,7 @@ func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) { reg.Register(KindSummary, r.renderSummary) reg.Register(KindIcon, r.renderIcon) reg.Register(ast.KindCodeSpan, r.renderCodeSpan) + reg.Register(KindAttention, r.renderAttention) reg.Register(KindTaskCheckBoxListItem, r.renderTaskCheckBoxListItem) reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox) } @@ -309,6 +324,27 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod return ast.WalkContinue, nil } +func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + if entering { + _, _ = w.WriteString(``) + + // TODO: Use code.gitea.io/gitea/modules/templates SVG function instead + // @yardenshoham didn't do it because when he tried to import code.gitea.io/gitea/modules/templates he got a cyclical import error + switch n.AttentionType { + case AttentionNote: + _, _ = w.WriteString(``) + case AttentionWarning: + _, _ = w.WriteString(``) + } + } else { + _, _ = w.WriteString("\n") + } + return ast.WalkContinue, nil +} + func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { n := node.(*ast.Document) diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index ff7165c13175f..1d2aabbb9b567 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -58,6 +58,12 @@ func createDefaultPolicy() *bluemonday.Policy { // For color preview policy.AllowAttrs("class").Matching(regexp.MustCompile(`^color-preview$`)).OnElements("span") + // For attention + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-\w+$`)).OnElements("span", "strong") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^svg octicon-\w+$`)).OnElements("svg") + policy.AllowAttrs("viewBox", "width", "height", "aria-hidden").OnElements("svg") + policy.AllowAttrs("fill-rule", "d").OnElements("path") + // For Chroma markdown plugin policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(chroma )?language-[\w-]+( display)?( is-loading)?$`)).OnElements("code") diff --git a/web_src/less/_base.less b/web_src/less/_base.less index f1691d81562d8..8b7886d16930f 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1732,6 +1732,20 @@ a.ui.card:hover, border-radius: .15em; } +.attention() { + font-weight: unset; +} + +.attention-note { + .attention; + color: var(--color-info-text); +} + +.attention-warning { + .attention; + color: var(--color-warning-text); +} + footer { background-color: var(--color-footer); border-top: 1px solid var(--color-secondary); From 4c85fcfddce36d7dd8bf1b7da0ee974f57070446 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 11:20:34 +0200 Subject: [PATCH 02/10] Update modules/markup/markdown/goldmark.go Co-authored-by: delvh --- modules/markup/markdown/goldmark.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index d95eb3b44f5c7..603fe1795e54e 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -324,6 +324,7 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod return ast.WalkContinue, nil } +// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { if entering { _, _ = w.WriteString(``) - // TODO: Use code.gitea.io/gitea/modules/templates SVG function instead - // @yardenshoham didn't do it because when he tried to import code.gitea.io/gitea/modules/templates he got a cyclical import error + var octiconType string switch n.AttentionType { case AttentionNote: - _, _ = w.WriteString(``) + octiconType = "info" case AttentionWarning: - _, _ = w.WriteString(``) + octiconType = "warning" } + _, _ = w.WriteString(string(svg.RenderHTML("octicon-" + octiconType))) } else { _, _ = w.WriteString("\n") } From 9afd6d4ad3620b12e1371975391d3d0ffbd0d5ef Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 17:52:46 +0000 Subject: [PATCH 05/10] Add case sensitivity --- modules/markup/markdown/ast.go | 4 ++-- modules/markup/markdown/goldmark.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/markup/markdown/ast.go b/modules/markup/markdown/ast.go index 420aef8b5a599..3d49620253e06 100644 --- a/modules/markup/markdown/ast.go +++ b/modules/markup/markdown/ast.go @@ -182,8 +182,8 @@ func IsColorPreview(node ast.Node) bool { } const ( - AttentionNote string = "note" - AttentionWarning string = "warning" + AttentionNote string = "Note" + AttentionWarning string = "Warning" ) // Attention is an inline for a color preview diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 9a0fc333f9e9b..9a77cfe8b9d9f 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -194,9 +194,9 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa _, isInBlockquote := grandparent.(*ast.Blockquote) _, blockquoteAlreadyAttentionMarked := grandparent.AttributeString(hasThisBlockquoteBeenAttentionMarked) if !blockquoteAlreadyAttentionMarked && isInBlockquote { - fullText := strings.ToLower(string(n.Text(reader.Source()))) + fullText := string(n.Text(reader.Source())) if fullText == AttentionNote || fullText == AttentionWarning { - v.SetAttributeString("class", []byte("attention-"+fullText)) + v.SetAttributeString("class", []byte("attention-"+strings.ToLower(fullText))) v.Parent().InsertBefore(v.Parent(), v, NewAttention(fullText)) grandparent.SetAttributeString(hasThisBlockquoteBeenAttentionMarked, []byte("yes")) } @@ -332,7 +332,7 @@ func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast if entering { _, _ = w.WriteString(``) var octiconType string From e40b966b3e0665563257d0068513e8d891e7d0bf Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 19:54:43 +0200 Subject: [PATCH 06/10] Update web_src/less/_base.less Co-authored-by: silverwind --- web_src/less/_base.less | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 8b7886d16930f..21787b24aa045 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1732,17 +1732,13 @@ a.ui.card:hover, border-radius: .15em; } -.attention() { - font-weight: unset; -} - .attention-note { - .attention; + font-weight: unset; color: var(--color-info-text); } .attention-warning { - .attention; + font-weight: unset; color: var(--color-warning-text); } From 0fc12a55adbe83283314aac067ececf3312d1400 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 18:09:41 +0000 Subject: [PATCH 07/10] Fix octicon --- modules/markup/markdown/goldmark.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 9a77cfe8b9d9f..0a19a3ef4e861 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -340,7 +340,7 @@ func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast case AttentionNote: octiconType = "info" case AttentionWarning: - octiconType = "warning" + octiconType = "alert" } _, _ = w.WriteString(string(svg.RenderHTML("octicon-" + octiconType))) } else { From ad76221305aab790d54559f6bc050ed9263497cc Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 18:13:56 +0000 Subject: [PATCH 08/10] Use set --- modules/markup/markdown/goldmark.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 0a19a3ef4e861..116ee5e930914 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -29,8 +29,6 @@ import ( var byteMailto = []byte("mailto:") -const hasThisBlockquoteBeenAttentionMarked = "has-this-blockquote-been-attention-marked" - // ASTTransformer is a default transformer of the goldmark tree. type ASTTransformer struct{} @@ -49,6 +47,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa ctx.TableOfContents = make([]markup.Header, 0, 100) } + attentionMarkedBlockquotes := make(container.Set[*ast.Blockquote]) _ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { if !entering { return ast.WalkContinue, nil @@ -190,15 +189,13 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa case *ast.Emphasis: // check if inside blockquote for attention, expected hierarchy is // Emphasis < Paragraph < Blockquote - grandparent := n.Parent().Parent() - _, isInBlockquote := grandparent.(*ast.Blockquote) - _, blockquoteAlreadyAttentionMarked := grandparent.AttributeString(hasThisBlockquoteBeenAttentionMarked) - if !blockquoteAlreadyAttentionMarked && isInBlockquote { + blockquote, isInBlockquote := n.Parent().Parent().(*ast.Blockquote) + if isInBlockquote && !attentionMarkedBlockquotes.Contains(blockquote) { fullText := string(n.Text(reader.Source())) if fullText == AttentionNote || fullText == AttentionWarning { v.SetAttributeString("class", []byte("attention-"+strings.ToLower(fullText))) v.Parent().InsertBefore(v.Parent(), v, NewAttention(fullText)) - grandparent.SetAttributeString(hasThisBlockquoteBeenAttentionMarked, []byte("yes")) + attentionMarkedBlockquotes.Add(blockquote) } } } From 3b73b8cae6d2b1b556cb05a654bbfff767606eac Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 19:00:30 +0000 Subject: [PATCH 09/10] Align vertically --- modules/markup/markdown/goldmark.go | 2 +- modules/markup/sanitizer.go | 3 ++- web_src/less/_base.less | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 116ee5e930914..84a02bfbbb39f 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -327,7 +327,7 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod // renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { if entering { - _, _ = w.WriteString(``) diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index 1d2aabbb9b567..c2a6c4a38f783 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -59,7 +59,8 @@ func createDefaultPolicy() *bluemonday.Policy { policy.AllowAttrs("class").Matching(regexp.MustCompile(`^color-preview$`)).OnElements("span") // For attention - policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-\w+$`)).OnElements("span", "strong") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-\w+$`)).OnElements("strong") + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-icon attention-\w+$`)).OnElements("span", "strong") policy.AllowAttrs("class").Matching(regexp.MustCompile(`^svg octicon-\w+$`)).OnElements("svg") policy.AllowAttrs("viewBox", "width", "height", "aria-hidden").OnElements("svg") policy.AllowAttrs("fill-rule", "d").OnElements("path") diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 21787b24aa045..a6b9e15a8f79b 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1732,6 +1732,10 @@ a.ui.card:hover, border-radius: .15em; } +.attention-icon { + vertical-align: middle; +} + .attention-note { font-weight: unset; color: var(--color-info-text); From dff8f96daba27a00ee78fba080dd4b5b2105c6d9 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 8 Nov 2022 21:36:51 +0200 Subject: [PATCH 10/10] Update web_src/less/_base.less Co-authored-by: silverwind --- web_src/less/_base.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/less/_base.less b/web_src/less/_base.less index a6b9e15a8f79b..43d8d711aa660 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1733,7 +1733,7 @@ a.ui.card:hover, } .attention-icon { - vertical-align: middle; + vertical-align: text-top; } .attention-note {