BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
68903277
Commit
68903277
authored
Mar 10, 2017
by
Douwe Maan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Copy code as GFM from diffs, blobs and GFM code blocks
parent
b7166806
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
70 additions
and
28 deletions
+70
-28
copy_as_gfm.js
app/assets/javascripts/copy_as_gfm.js
+60
-12
dm-copy-code-as-gfm.yml
changelogs/unreleased/dm-copy-code-as-gfm.yml
+4
-0
syntax_highlight_filter.rb
lib/banzai/filter/syntax_highlight_filter.rb
+1
-12
highlight.rb
lib/gitlab/highlight.rb
+2
-2
html_gitlab.rb
lib/rouge/formatters/html_gitlab.rb
+3
-2
copy_as_gfm_spec.rb
spec/features/copy_as_gfm_spec.rb
+0
-0
No files found.
app/assets/javascripts/copy_as_gfm.js
View file @
68903277
...
...
@@ -118,10 +118,10 @@ const gfmRules = {
},
SyntaxHighlightFilter
:
{
'pre.code.highlight'
(
el
,
t
)
{
const
text
=
t
.
trim
();
const
text
=
t
.
trim
Right
();
let
lang
=
el
.
getAttribute
(
'lang'
);
if
(
lang
===
'plaintext'
)
{
if
(
!
lang
||
lang
===
'plaintext'
)
{
lang
=
''
;
}
...
...
@@ -157,7 +157,7 @@ const gfmRules = {
const
backticks
=
Array
(
backtickCount
+
1
).
join
(
'`'
);
const
spaceOrNoSpace
=
backtickCount
>
1
?
' '
:
''
;
return
backticks
+
spaceOrNoSpace
+
text
+
spaceOrNoSpace
+
backticks
;
return
backticks
+
spaceOrNoSpace
+
text
.
trim
()
+
spaceOrNoSpace
+
backticks
;
},
'blockquote'
(
el
,
text
)
{
return
text
.
trim
().
split
(
'
\
n'
).
map
(
s
=>
`>
${
s
}
`
.
trim
()).
join
(
'
\
n'
);
...
...
@@ -273,28 +273,29 @@ const gfmRules = {
class
CopyAsGFM
{
constructor
()
{
$
(
document
).
on
(
'copy'
,
'.md, .wiki'
,
this
.
handleCopy
);
$
(
document
).
on
(
'paste'
,
'.js-gfm-input'
,
this
.
handlePaste
);
$
(
document
).
on
(
'copy'
,
'.md, .wiki'
,
(
e
)
=>
{
this
.
copyAsGFM
(
e
,
CopyAsGFM
.
transformGFMSelection
);
});
$
(
document
).
on
(
'copy'
,
'pre.code.highlight, .diff-content .line_content'
,
(
e
)
=>
{
this
.
copyAsGFM
(
e
,
CopyAsGFM
.
transformCodeSelection
);
});
$
(
document
).
on
(
'paste'
,
'.js-gfm-input'
,
this
.
pasteGFM
.
bind
(
this
));
}
handleCopy
(
e
)
{
copyAsGFM
(
e
,
transformer
)
{
const
clipboardData
=
e
.
originalEvent
.
clipboardData
;
if
(
!
clipboardData
)
return
;
const
documentFragment
=
window
.
gl
.
utils
.
getSelectedFragment
();
if
(
!
documentFragment
)
return
;
// If the documentFragment contains more than just Markdown, don't copy as GFM.
if
(
documentFragment
.
querySelector
(
'.md, .wiki'
)
)
return
;
const
el
=
transformer
(
documentFragment
.
cloneNode
(
true
));
if
(
!
el
)
return
;
e
.
preventDefault
();
clipboardData
.
setData
(
'text/plain'
,
documentFragment
.
textContent
);
e
.
stopPropagation
(
);
c
onst
gfm
=
CopyAsGFM
.
nodeToGFM
(
documentFragm
ent
);
clipboardData
.
setData
(
'text/x-gfm'
,
gfm
);
c
lipboardData
.
setData
(
'text/plain'
,
el
.
textCont
ent
);
clipboardData
.
setData
(
'text/x-gfm'
,
CopyAsGFM
.
nodeToGFM
(
el
)
);
}
handlePaste
(
e
)
{
pasteGFM
(
e
)
{
const
clipboardData
=
e
.
originalEvent
.
clipboardData
;
if
(
!
clipboardData
)
return
;
...
...
@@ -306,7 +307,54 @@ class CopyAsGFM {
window
.
gl
.
utils
.
insertText
(
e
.
target
,
gfm
);
}
static
transformGFMSelection
(
documentFragment
)
{
// If the documentFragment contains more than just Markdown, don't copy as GFM.
if
(
documentFragment
.
querySelector
(
'.md, .wiki'
))
return
null
;
return
documentFragment
;
}
static
transformCodeSelection
(
documentFragment
)
{
const
lineEls
=
documentFragment
.
querySelectorAll
(
'.line'
);
let
codeEl
;
if
(
lineEls
.
length
>
1
)
{
codeEl
=
document
.
createElement
(
'pre'
);
codeEl
.
className
=
'code highlight'
;
const
lang
=
lineEls
[
0
].
getAttribute
(
'lang'
);
if
(
lang
)
{
codeEl
.
setAttribute
(
'lang'
,
lang
);
}
}
else
{
codeEl
=
document
.
createElement
(
'code'
);
}
if
(
lineEls
.
length
>
0
)
{
for
(
let
i
=
0
;
i
<
lineEls
.
length
;
i
+=
1
)
{
const
lineEl
=
lineEls
[
i
];
codeEl
.
appendChild
(
lineEl
);
codeEl
.
appendChild
(
document
.
createTextNode
(
'
\
n'
));
}
}
else
{
codeEl
.
appendChild
(
documentFragment
);
}
return
codeEl
;
}
static
selectionToGFM
(
documentFragment
,
transformer
)
{
const
el
=
transformer
(
documentFragment
.
cloneNode
(
true
));
if
(
!
el
)
return
null
;
return
CopyAsGFM
.
nodeToGFM
(
el
);
}
static
nodeToGFM
(
node
)
{
if
(
node
.
nodeType
===
Node
.
COMMENT_NODE
)
{
return
''
;
}
if
(
node
.
nodeType
===
Node
.
TEXT_NODE
)
{
return
node
.
textContent
;
}
...
...
changelogs/unreleased/dm-copy-code-as-gfm.yml
0 → 100644
View file @
68903277
---
title
:
Copy code as GFM from diffs, blobs and GFM code blocks
merge_request
:
author
:
lib/banzai/filter/syntax_highlight_filter.rb
View file @
68903277
...
...
@@ -5,8 +5,6 @@ module Banzai
# HTML Filter to highlight fenced code blocks
#
class
SyntaxHighlightFilter
<
HTML
::
Pipeline
::
Filter
include
Rouge
::
Plugins
::
Redcarpet
def
call
doc
.
search
(
'pre > code'
).
each
do
|
node
|
highlight_node
(
node
)
...
...
@@ -23,7 +21,7 @@ module Banzai
lang
=
lexer
.
tag
begin
code
=
format
(
lex
(
lexer
,
code
)
)
code
=
Rouge
::
Formatters
::
HTMLGitlab
.
format
(
lex
(
lexer
,
code
),
tag:
lang
)
css_classes
<<
" js-syntax-highlight
#{
lang
}
"
rescue
...
...
@@ -45,10 +43,6 @@ module Banzai
lexer
.
lex
(
code
)
end
def
format
(
tokens
)
rouge_formatter
.
format
(
tokens
)
end
def
lexer_for
(
language
)
(
Rouge
::
Lexer
.
find
(
language
)
||
Rouge
::
Lexers
::
PlainText
).
new
end
...
...
@@ -57,11 +51,6 @@ module Banzai
# Replace the parent `pre` element with the entire highlighted block
node
.
parent
.
replace
(
highlighted
)
end
# Override Rouge::Plugins::Redcarpet#rouge_formatter
def
rouge_formatter
(
lexer
=
nil
)
@rouge_formatter
||=
Rouge
::
Formatters
::
HTML
.
new
end
end
end
end
lib/gitlab/highlight.rb
View file @
68903277
...
...
@@ -14,7 +14,7 @@ module Gitlab
end
def
initialize
(
blob_name
,
blob_content
,
repository:
nil
)
@formatter
=
Rouge
::
Formatters
::
HTMLGitlab
.
new
@formatter
=
Rouge
::
Formatters
::
HTMLGitlab
@repository
=
repository
@blob_name
=
blob_name
@blob_content
=
blob_content
...
...
@@ -28,7 +28,7 @@ module Gitlab
hl_lexer
=
self
.
lexer
end
@formatter
.
format
(
hl_lexer
.
lex
(
text
,
continue:
continue
)).
html_safe
@formatter
.
format
(
hl_lexer
.
lex
(
text
,
continue:
continue
)
,
tag:
hl_lexer
.
tag
).
html_safe
rescue
@formatter
.
format
(
Rouge
::
Lexers
::
PlainText
.
lex
(
text
)).
html_safe
end
...
...
lib/rouge/formatters/html_gitlab.rb
View file @
68903277
...
...
@@ -6,9 +6,10 @@ module Rouge
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
#
# [+linenostart+] The line number for the first line (default: 1).
def
initialize
(
linenostart:
1
)
def
initialize
(
linenostart:
1
,
tag:
nil
)
@linenostart
=
linenostart
@line_number
=
linenostart
@tag
=
tag
end
def
stream
(
tokens
,
&
b
)
...
...
@@ -17,7 +18,7 @@ module Rouge
yield
"
\n
"
unless
is_first
is_first
=
false
yield
%(<span id="LC#{@line_number}" class="line">)
yield
%(<span id="LC#{@line_number}" class="line"
lang="#{@tag}"
>)
line
.
each
{
|
token
,
value
|
yield
span
(
token
,
value
.
chomp
)
}
yield
%(</span>)
...
...
spec/features/copy_as_gfm_spec.rb
View file @
68903277
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment