Copy diff file path as GFM
This commit is contained in:
parent
00e00cacf8
commit
12c18ee546
20 changed files with 88 additions and 39 deletions
|
@ -38,9 +38,35 @@ showTooltip = function(target, title) {
|
|||
};
|
||||
|
||||
$(function() {
|
||||
var clipboard;
|
||||
|
||||
clipboard = new Clipboard('[data-clipboard-target], [data-clipboard-text]');
|
||||
const clipboard = new Clipboard('[data-clipboard-target], [data-clipboard-text]');
|
||||
clipboard.on('success', genericSuccess);
|
||||
return clipboard.on('error', genericError);
|
||||
clipboard.on('error', genericError);
|
||||
|
||||
// This a workaround around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
|
||||
// The Ruby `clipboard_button` helper sneaks a JSON hash with `text` and `gfm` keys into the `data-clipboard-text`
|
||||
// attribute that ClipboardJS reads from.
|
||||
// When ClipboardJS creates a new `textarea` (directly inside `body`, with a `readonly` attribute`), sets its value
|
||||
// to the value of this data attribute, focusses on it, and finally programmatically issues the 'Copy' command,
|
||||
// this code intercepts the copy command/event at the last minute to deconstruct this JSON hash and set the
|
||||
// `text/plain` and `text/x-gfm` copy data types to the intended values.
|
||||
$(document).on('copy', 'body > textarea[readonly]', function(e) {
|
||||
const clipboardData = e.originalEvent.clipboardData;
|
||||
if (!clipboardData) return;
|
||||
|
||||
const text = e.target.value;
|
||||
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(text);
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!json.text || !json.gfm) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
clipboardData.setData('text/plain', json.text);
|
||||
clipboardData.setData('text/x-gfm', json.gfm);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -210,13 +210,13 @@ module BlobHelper
|
|||
end
|
||||
|
||||
def copy_file_path_button(file_path)
|
||||
clipboard_button(clipboard_text: file_path, class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard')
|
||||
clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard')
|
||||
end
|
||||
|
||||
def copy_blob_content_button(blob)
|
||||
return if markup?(blob.name)
|
||||
|
||||
clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{blob.id}']", class: "btn btn-sm", title: "Copy content to clipboard")
|
||||
clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}']", class: "btn btn-sm", title: "Copy content to clipboard")
|
||||
end
|
||||
|
||||
def open_raw_file_button(path)
|
||||
|
|
|
@ -1,23 +1,42 @@
|
|||
module ButtonHelper
|
||||
# Output a "Copy to Clipboard" button
|
||||
#
|
||||
# data - Data attributes passed to `content_tag`
|
||||
# data - Data attributes passed to `content_tag` (default: {}):
|
||||
# :text - Text to copy (optional)
|
||||
# :gfm - GitLab Flavored Markdown to copy, if different from `text` (optional)
|
||||
# :target - Selector for target element to copy from (optional)
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# # Define the clipboard's text
|
||||
# clipboard_button(clipboard_text: "Foo")
|
||||
# clipboard_button(text: "Foo")
|
||||
# # => "<button class='...' data-clipboard-text='Foo'>...</button>"
|
||||
#
|
||||
# # Define the target element
|
||||
# clipboard_button(clipboard_target: "div#foo")
|
||||
# clipboard_button(target: "div#foo")
|
||||
# # => "<button class='...' data-clipboard-target='div#foo'>...</button>"
|
||||
#
|
||||
# See http://clipboardjs.com/#usage
|
||||
def clipboard_button(data = {})
|
||||
css_class = data[:class] || 'btn-clipboard btn-transparent'
|
||||
title = data[:title] || 'Copy to clipboard'
|
||||
|
||||
# This supports code in app/assets/javascripts/copy_to_clipboard.js that
|
||||
# works around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
|
||||
if text = data.delete(:text)
|
||||
data[:clipboard_text] =
|
||||
if gfm = data.delete(:gfm)
|
||||
{ text: text, gfm: gfm }
|
||||
else
|
||||
text
|
||||
end
|
||||
end
|
||||
|
||||
target = data.delete(:target)
|
||||
data[:clipboard_target] = target if target
|
||||
|
||||
data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
|
||||
|
||||
content_tag :button,
|
||||
icon('clipboard', 'aria-hidden': 'true'),
|
||||
class: "btn #{css_class}",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
Your New Personal Access Token
|
||||
.form-group
|
||||
= text_field_tag 'created-personal-access-token', flash[:personal_access_token], readonly: true, class: "form-control", 'aria-describedby' => "created-personal-access-token-help-block"
|
||||
= clipboard_button(clipboard_text: flash[:personal_access_token], title: "Copy personal access token to clipboard", placement: "left")
|
||||
= clipboard_button(text: flash[:personal_access_token], title: "Copy personal access token to clipboard", placement: "left")
|
||||
%span#created-personal-access-token-help-block.help-block.text-danger Make sure you save it - you won't be able to access it again.
|
||||
|
||||
%hr
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
- if @project && event.project != @project
|
||||
%span at
|
||||
%strong= link_to_project event.project
|
||||
= clipboard_button(clipboard_text: event.ref_name, class: 'btn-clipboard btn-transparent', title: 'Copy branch to clipboard')
|
||||
= clipboard_button(text: event.ref_name, class: 'btn-clipboard btn-transparent', title: 'Copy branch to clipboard')
|
||||
#{time_ago_with_tooltip(event.created_at)}
|
||||
|
||||
.pull-right
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.page-content-header
|
||||
.header-main-content
|
||||
%strong Commit #{@commit.short_id}
|
||||
= clipboard_button(clipboard_text: @commit.id, title: "Copy commit SHA to clipboard")
|
||||
= clipboard_button(text: @commit.id, title: "Copy commit SHA to clipboard")
|
||||
%span.hidden-xs authored
|
||||
#{time_ago_with_tooltip(@commit.authored_date)}
|
||||
%span by
|
||||
|
|
|
@ -37,6 +37,6 @@
|
|||
.commit-actions.flex-row.hidden-xs
|
||||
- if commit.status(ref)
|
||||
= render_commit_status(commit, ref: ref)
|
||||
= clipboard_button(clipboard_text: commit.id, title: "Copy commit SHA to clipboard")
|
||||
= clipboard_button(text: commit.id, title: "Copy commit SHA to clipboard")
|
||||
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
|
||||
= link_to_browse_code(project, commit)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
.email-modal-input-group.input-group
|
||||
= text_field_tag :issue_email, email, class: "monospace js-select-on-focus form-control", readonly: true
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#issue_email')
|
||||
= clipboard_button(target: '#issue_email')
|
||||
%p
|
||||
The subject will be used as the title of the new issue, and the message will be the description.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
%p
|
||||
%strong Step 1.
|
||||
Fetch and check out the branch for this merge request
|
||||
= clipboard_button(clipboard_target: "pre#merge-info-1", title: "Copy commands to clipboard")
|
||||
= clipboard_button(target: "pre#merge-info-1", title: "Copy commands to clipboard")
|
||||
%pre.dark#merge-info-1
|
||||
- if @merge_request.for_fork?
|
||||
:preserve
|
||||
|
@ -25,7 +25,7 @@
|
|||
%p
|
||||
%strong Step 3.
|
||||
Merge the branch and fix any conflicts that come up
|
||||
= clipboard_button(clipboard_target: "pre#merge-info-3", title: "Copy commands to clipboard")
|
||||
= clipboard_button(target: "pre#merge-info-3", title: "Copy commands to clipboard")
|
||||
%pre.dark#merge-info-3
|
||||
- if @merge_request.for_fork?
|
||||
:preserve
|
||||
|
@ -38,7 +38,7 @@
|
|||
%p
|
||||
%strong Step 4.
|
||||
Push the result of the merge to GitLab
|
||||
= clipboard_button(clipboard_target: "pre#merge-info-4", title: "Copy commands to clipboard")
|
||||
= clipboard_button(target: "pre#merge-info-4", title: "Copy commands to clipboard")
|
||||
%pre.dark#merge-info-4
|
||||
:preserve
|
||||
git push origin #{h @merge_request.target_branch}
|
||||
|
|
|
@ -46,4 +46,4 @@
|
|||
\...
|
||||
%span.js-details-content.hide
|
||||
= link_to @pipeline.sha, namespace_project_commit_path(@project.namespace, @project, @pipeline.sha), class: "monospace commit-hash-full"
|
||||
= clipboard_button(clipboard_text: @pipeline.sha, title: "Copy commit SHA to clipboard")
|
||||
= clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%tr.tag
|
||||
%td
|
||||
= escape_once(tag.name)
|
||||
= clipboard_button(clipboard_text: "docker pull #{tag.path}")
|
||||
= clipboard_button(text: "docker pull #{tag.path}")
|
||||
%td
|
||||
- if tag.revision
|
||||
%span.has-tooltip{ title: "#{tag.revision}" }
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#display_name')
|
||||
= clipboard_button(target: '#display_name')
|
||||
|
||||
.form-group
|
||||
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#description')
|
||||
= clipboard_button(target: '#description')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
|
||||
|
@ -46,7 +46,7 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#request_url')
|
||||
= clipboard_button(target: '#request_url')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
|
||||
|
@ -57,14 +57,14 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#response_username')
|
||||
= clipboard_button(target: '#response_username')
|
||||
|
||||
.form-group
|
||||
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#response_icon')
|
||||
= clipboard_button(target: '#response_icon')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
|
||||
|
@ -75,14 +75,14 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_hint')
|
||||
= clipboard_button(target: '#autocomplete_hint')
|
||||
|
||||
.form-group
|
||||
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_description')
|
||||
= clipboard_button(target: '#autocomplete_description')
|
||||
|
||||
%hr
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#url')
|
||||
= clipboard_button(target: '#url')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Method', class: 'col-sm-2 col-xs-12 control-label'
|
||||
|
@ -51,7 +51,7 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :customize_name, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#customize_name')
|
||||
= clipboard_button(target: '#customize_name')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label'
|
||||
|
@ -68,21 +68,21 @@
|
|||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_description')
|
||||
= clipboard_button(target: '#autocomplete_description')
|
||||
|
||||
.form-group
|
||||
= label_tag :autocomplete_usage_hint, 'Autocomplete usage hint', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_usage_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_usage_hint')
|
||||
= clipboard_button(target: '#autocomplete_usage_hint')
|
||||
|
||||
.form-group
|
||||
= label_tag :descriptive_label, 'Descriptive label', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :descriptive_label, 'Perform common operations on GitLab project', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#descriptive_label')
|
||||
= clipboard_button(target: '#descriptive_label')
|
||||
|
||||
%hr
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
%i.fa.fa-angle-right
|
||||
%small.light
|
||||
= link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
|
||||
= clipboard_button(clipboard_text: @commit.id, title: "Copy commit SHA to clipboard")
|
||||
= clipboard_button(text: @commit.id, title: "Copy commit SHA to clipboard")
|
||||
= time_ago_with_tooltip(@commit.committed_date)
|
||||
\-
|
||||
= @commit.full_title
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%td
|
||||
- if can?(current_user, :admin_trigger, trigger)
|
||||
%span= trigger.token
|
||||
= clipboard_button(clipboard_text: trigger.token, title: "Copy trigger token to clipboard")
|
||||
= clipboard_button(text: trigger.token, title: "Copy trigger token to clipboard")
|
||||
- else
|
||||
%span= trigger.short_token
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#project_clone', title: "Copy URL to clipboard")
|
||||
= clipboard_button(target: '#project_clone', title: "Copy URL to clipboard")
|
||||
|
||||
:javascript
|
||||
$('ul.clone-options-dropdown a').on('click',function(e){
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
- if impersonation
|
||||
%td.token-token-container
|
||||
= text_field_tag 'impersonation-token-token', token.token, readonly: true, class: "form-control"
|
||||
= clipboard_button(clipboard_text: token.token)
|
||||
= clipboard_button(text: token.token)
|
||||
- path = impersonation ? revoke_admin_user_impersonation_token_path(token.user, token) : revoke_profile_personal_access_token_path(token)
|
||||
%td= link_to "Revoke", path, method: :put, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
|
||||
- else
|
||||
|
|
|
@ -160,13 +160,13 @@
|
|||
- project_ref = cross_project_reference(@project, issuable)
|
||||
.block.project-reference
|
||||
.sidebar-collapsed-icon.dont-change-state
|
||||
= clipboard_button(clipboard_text: project_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
= clipboard_button(text: project_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
.cross-project-reference.hide-collapsed
|
||||
%span
|
||||
Reference:
|
||||
%cite{ title: project_ref }
|
||||
= project_ref
|
||||
= clipboard_button(clipboard_text: project_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
= clipboard_button(text: project_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
|
||||
:javascript
|
||||
gl.IssuableResource = new gl.SubbableResource('#{issuable_json_path(issuable)}');
|
||||
|
|
|
@ -122,10 +122,10 @@
|
|||
- if milestone_ref.present?
|
||||
.block.reference
|
||||
.sidebar-collapsed-icon.dont-change-state
|
||||
= clipboard_button(clipboard_text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
= clipboard_button(text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
.cross-project-reference.hide-collapsed
|
||||
%span
|
||||
Reference:
|
||||
%cite{ title: milestone_ref }
|
||||
= milestone_ref
|
||||
= clipboard_button(clipboard_text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
= clipboard_button(text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
|
||||
|
|
4
changelogs/unreleased/dm-copy-diff-file-title-as-gfm.yml
Normal file
4
changelogs/unreleased/dm-copy-diff-file-title-as-gfm.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: After copying a diff file or blob path, pasting it into a comment field will format it as Markdown.
|
||||
merge_request: 9876
|
||||
author:
|
Loading…
Reference in a new issue