diff options
5 files changed, 91 insertions, 3 deletions
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js index b9b894b3348..1e0c05eff08 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js @@ -8,6 +8,7 @@ const PLAINTEXT_LANG = 'plaintext'; // - Banzai::Filter::SyntaxHighlightFilter // - Banzai::Filter::MathFilter // - Banzai::Filter::MermaidFilter +// - Banzai::Filter::SuggestionFilter export default class CodeBlock extends BaseCodeBlock { get schema() { return { @@ -20,7 +21,7 @@ export default class CodeBlock extends BaseCodeBlock { lang: { default: PLAINTEXT_LANG }, }, parseDOM: [ - // Matches HTML generated by Banzai::Filter::SyntaxHighlightFilter, Banzai::Filter::MathFilter or Banzai::Filter::MermaidFilter + // Matches HTML generated by Banzai::Filter::SyntaxHighlightFilter, Banzai::Filter::MathFilter, Banzai::Filter::MermaidFilter, or Banzai::Filter::SuggestionFilter { tag: 'pre.code.highlight', preserveWhitespace: 'full', @@ -39,7 +40,7 @@ export default class CodeBlock extends BaseCodeBlock { contentElement: 'annotation[encoding="application/x-tex"]', attrs: { lang: 'math' }, }, - // Matches HTML generated by Banzai::Filter::MathFilter, + // Matches HTML generated by Banzai::Filter::MermaidFilter, // after being transformed by app/assets/javascripts/behaviors/markdown/render_mermaid.js { tag: 'svg.mermaid', @@ -47,6 +48,25 @@ export default class CodeBlock extends BaseCodeBlock { contentElement: 'text.source', attrs: { lang: 'mermaid' }, }, + // Matches HTML generated by Banzai::Filter::SuggestionFilter, + // after being transformed by app/assets/javascripts/vue_shared/components/markdown/suggestions.vue + { + tag: '.md-suggestion', + skip: true, + }, + { + tag: '.md-suggestion-header', + ignore: true, + }, + { + tag: '.md-suggestion-diff', + preserveWhitespace: 'full', + getContent: (el, schema) => + [...el.querySelectorAll('.line_content.new span')].map(span => + schema.text(span.innerText), + ), + attrs: { lang: 'suggestion' }, + }, ], toDOM: node => ['pre', { class: 'code highlight', lang: node.attrs.lang }, ['code', 0]], }; diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue index b9f884074d0..a351ca62c94 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue @@ -42,7 +42,7 @@ export default { </script> <template> - <div> + <div class="md-suggestion"> <suggestion-diff-header class="qa-suggestion-diff-header" :can-apply="suggestion.appliable && suggestion.current_user.can_apply && !disabled" diff --git a/changelogs/unreleased/dm-copy-suggestion-as-gfm.yml b/changelogs/unreleased/dm-copy-suggestion-as-gfm.yml new file mode 100644 index 00000000000..96115e6ade1 --- /dev/null +++ b/changelogs/unreleased/dm-copy-suggestion-as-gfm.yml @@ -0,0 +1,5 @@ +--- +title: Allow suggestions to be copied and pasted as GFM +merge_request: +author: +type: fixed diff --git a/lib/banzai/filter/suggestion_filter.rb b/lib/banzai/filter/suggestion_filter.rb index 307ea449140..9950db373d8 100644 --- a/lib/banzai/filter/suggestion_filter.rb +++ b/lib/banzai/filter/suggestion_filter.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/code_block.js module Banzai module Filter class SuggestionFilter < HTML::Pipeline::Filter diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb index 92dee494b7e..16754035076 100644 --- a/spec/features/markdown/copy_as_gfm_spec.rb +++ b/spec/features/markdown/copy_as_gfm_spec.rb @@ -403,6 +403,68 @@ describe 'Copy as GFM', :js do end verify( + 'SuggestionFilter: suggestion as converted from GFM to HTML', + + <<~GFM + ```suggestion + New + And newer + ``` + GFM + ) + + aggregate_failures('SuggestionFilter: suggestion as transformed from HTML to Vue component') do + gfm = <<~GFM + ```suggestion + New + And newer + ``` + GFM + + html = <<~HTML + <div class="md-suggestion"> + <div class="md-suggestion-header border-bottom-0 mt-2 qa-suggestion-diff-header"> + <div class="qa-suggestion-diff-header font-weight-bold"> + Suggested change + <a href="/gitlab/help/user/discussions/index.md#suggest-changes" aria-label="Help" class="js-help-btn"> + <svg aria-hidden="true" class="s16 ic-question-o link-highlight"> + <use xlink:href="/gitlab/assets/icons.svg#question-o"></use> + </svg> + </a> + </div> + <!----> + <button type="button" class="btn qa-apply-btn">Apply suggestion</button> + </div> + <table class="mb-3 md-suggestion-diff js-syntax-highlight code white"> + <tbody> + <tr class="line_holder old"> + <td class="diff-line-num old_line qa-old-diff-line-number old">9</td> + <td class="diff-line-num new_line old"></td> + <td class="line_content old"><span>Old + </span></td> + </tr> + <tr class="line_holder new"> + <td class="diff-line-num old_line new"></td> + <td class="diff-line-num new_line qa-new-diff-line-number new">9</td> + <td class="line_content new"><span>New + </span></td> + </tr> + <tr class="line_holder new"> + <td class="diff-line-num old_line new"></td> + <td class="diff-line-num new_line qa-new-diff-line-number new">10</td> + <td class="line_content new"><span> And newer + </span></td> + </tr> + </tbody> + </table> + </div> + HTML + + output_gfm = html_to_gfm(html) + expect(output_gfm.strip).to eq(gfm.strip) + end + + verify( 'SanitizationFilter', <<~GFM |