From 2c2ac80030f653f51290cbbdc6947beff078462b Mon Sep 17 00:00:00 2001 From: Gusted Date: Thu, 24 Oct 2024 01:07:53 +0200 Subject: [PATCH] feat: Add partial quoting - If you select a portion of the comment, `Quote reply` will not only quote that portion and not copy paste the whole text as it previously did. This is achieved by using the `@github/quote-selection` package. - There's preprocessing to ensure Forgejo-flavored markdown syntax is preserved. - e2e test added. - Resolves #1342 --- modules/markup/html.go | 10 +- modules/markup/html_test.go | 26 ++-- modules/markup/markdown/markdown_test.go | 30 ++--- modules/markup/sanitizer.go | 3 +- modules/markup/sanitizer_test.go | 7 ++ modules/templates/util_render_test.go | 18 +-- package-lock.json | 7 ++ package.json | 1 + release-notes/5677.md | 1 + routers/api/v1/misc/markup_test.go | 2 +- templates/repo/diff/comments.tmpl | 2 +- templates/repo/issue/view_content.tmpl | 2 +- .../repo/issue/view_content/comments.tmpl | 4 +- .../repo/issue/view_content/context_menu.tmpl | 2 +- .../repo/issue/view_content/conversation.tmpl | 2 +- tests/e2e/e2e_test.go | 4 +- tests/e2e/fixtures/comment.yml | 22 ++++ tests/e2e/fixtures/review.yml | 8 ++ tests/e2e/issue-comment.test.e2e.js | 107 +++++++++++++++++ tests/integration/repo_issue_title_test.go | 2 +- web_src/js/features/repo-legacy.js | 111 +++++++++++++++--- 21 files changed, 303 insertions(+), 68 deletions(-) create mode 100644 release-notes/5677.md create mode 100644 tests/e2e/fixtures/comment.yml create mode 100644 tests/e2e/fixtures/review.yml diff --git a/modules/markup/html.go b/modules/markup/html.go index 2e65827bf7..3355c021ce 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -472,7 +472,7 @@ func createInlineCode(content string) *html.Node { return code } -func createEmoji(content, class, name string) *html.Node { +func createEmoji(content, class, name, alias string) *html.Node { span := &html.Node{ Type: html.ElementNode, Data: atom.Span.String(), @@ -484,6 +484,9 @@ func createEmoji(content, class, name string) *html.Node { if name != "" { span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: name}) } + if alias != "" { + span.Attr = append(span.Attr, html.Attribute{Key: "data-alias", Val: alias}) + } text := &html.Node{ Type: html.TextNode, @@ -502,6 +505,7 @@ func createCustomEmoji(alias string) *html.Node { } span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: "emoji"}) span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: alias}) + span.Attr = append(span.Attr, html.Attribute{Key: "data-alias", Val: alias}) img := &html.Node{ Type: html.ElementNode, @@ -1147,7 +1151,7 @@ func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) { continue } - replaceContent(node, m[0], m[1], createEmoji(converted.Emoji, "emoji", converted.Description)) + replaceContent(node, m[0], m[1], createEmoji(converted.Emoji, "emoji", converted.Description, alias)) node = node.NextSibling.NextSibling start = 0 } @@ -1169,7 +1173,7 @@ func emojiProcessor(ctx *RenderContext, node *html.Node) { start = m[1] val := emoji.FromCode(codepoint) if val != nil { - replaceContent(node, m[0], m[1], createEmoji(codepoint, "emoji", val.Description)) + replaceContent(node, m[0], m[1], createEmoji(codepoint, "emoji", val.Description, val.Aliases[0])) node = node.NextSibling.NextSibling start = 0 } diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index 68d1ada5b3..50ea70905c 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -329,42 +329,42 @@ func TestRender_emoji(t *testing.T) { for i := range emoji.GemojiData { test( emoji.GemojiData[i].Emoji, - `

`+emoji.GemojiData[i].Emoji+`

`) + `

`+emoji.GemojiData[i].Emoji+`

`) } for i := range emoji.GemojiData { test( ":"+emoji.GemojiData[i].Aliases[0]+":", - `

`+emoji.GemojiData[i].Emoji+`

`) + `

`+emoji.GemojiData[i].Emoji+`

`) } // Text that should be turned into or recognized as emoji test( ":gitea:", - `

:gitea:

`) + `

:gitea:

`) test( ":custom-emoji:", `

:custom-emoji:

`) setting.UI.CustomEmojisMap["custom-emoji"] = ":custom-emoji:" test( ":custom-emoji:", - `

:custom-emoji:

`) + `

:custom-emoji:

`) test( "θΏ™ζ˜―ε­—η¬¦:1::+1: some🐊 \U0001f44d:custom-emoji: :gitea:", - `

θΏ™ζ˜―ε­—η¬¦:1:πŸ‘ some🐊 `+ - `πŸ‘:custom-emoji: `+ - `:gitea:

`) + `

θΏ™ζ˜―ε­—η¬¦:1:πŸ‘ some🐊 `+ + `πŸ‘:custom-emoji: `+ + `:gitea:

`) test( "Some text with πŸ˜„ in the middle", - `

Some text with πŸ˜„ in the middle

`) + `

Some text with πŸ˜„ in the middle

`) test( "Some text with :smile: in the middle", - `

Some text with πŸ˜„ in the middle

`) + `

Some text with πŸ˜„ in the middle

`) test( "Some text with πŸ˜„πŸ˜„ 2 emoji next to each other", - `

Some text with πŸ˜„πŸ˜„ 2 emoji next to each other

`) + `

Some text with πŸ˜„πŸ˜„ 2 emoji next to each other

`) test( "😎πŸ€ͺπŸ”πŸ€‘β“", - `

😎πŸ€ͺπŸ”πŸ€‘β“

`) + `

😎πŸ€ͺπŸ”πŸ€‘β“

`) // should match nothing test( @@ -601,10 +601,10 @@ func TestPostProcess_RenderDocument(t *testing.T) { // Test that other post processing still works. test( ":gitea:", - `:gitea:`) + `:gitea:`) test( "Some text with πŸ˜„ in the middle", - `Some text with πŸ˜„ in the middle`) + `Some text with πŸ˜„ in the middle`) test("http://localhost:3000/person/repo/issues/4#issuecomment-1234", `person/repo#4 (comment)`) } diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index e3dc6c9655..84a7c5f882 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -135,8 +135,8 @@ func testAnswers(baseURLContent, baseURLImages string) []string {

See commit 65f1bf27bc

Ideas and codes