Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8dfad143
Commit
8dfad143
authored
Jan 14, 2016
by
Douwe Maan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add inline diff markers in highlighted diffs.
parent
83e4fc18
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
187 additions
and
40 deletions
+187
-40
app/controllers/projects/blob_controller.rb
app/controllers/projects/blob_controller.rb
+1
-1
app/views/projects/diffs/_parallel_view.html.haml
app/views/projects/diffs/_parallel_view.html.haml
+2
-2
app/views/projects/diffs/_text_file.html.haml
app/views/projects/diffs/_text_file.html.haml
+1
-1
lib/gitlab/diff/file.rb
lib/gitlab/diff/file.rb
+1
-1
lib/gitlab/diff/highlight.rb
lib/gitlab/diff/highlight.rb
+173
-33
lib/gitlab/highlight.rb
lib/gitlab/highlight.rb
+7
-0
spec/lib/gitlab/diff/highlight_spec.rb
spec/lib/gitlab/diff/highlight_spec.rb
+2
-2
No files found.
app/controllers/projects/blob_controller.rb
View file @
8dfad143
...
@@ -66,7 +66,7 @@ class Projects::BlobController < Projects::ApplicationController
...
@@ -66,7 +66,7 @@ class Projects::BlobController < Projects::ApplicationController
def
diff
def
diff
@form
=
UnfoldForm
.
new
(
params
)
@form
=
UnfoldForm
.
new
(
params
)
@lines
=
Gitlab
::
Diff
::
Highlight
.
process_file
(
repository
,
@ref
,
@path
)
@lines
=
Gitlab
::
Highlight
.
highlight_lines
(
repository
,
@ref
,
@path
)
@lines
=
@lines
[
@form
.
since
-
1
..
@form
.
to
-
1
]
@lines
=
@lines
[
@form
.
since
-
1
..
@form
.
to
-
1
]
if
@form
.
bottom?
if
@form
.
bottom?
...
...
app/views/projects/diffs/_parallel_view.html.haml
View file @
8dfad143
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
=
link_to
raw
(
left
[
:number
]),
"#
#{
left
[
:line_code
]
}
"
,
id:
left
[
:line_code
]
=
link_to
raw
(
left
[
:number
]),
"#
#{
left
[
:line_code
]
}
"
,
id:
left
[
:line_code
]
-
if
@comments_allowed
&&
can?
(
current_user
,
:create_note
,
@project
)
-
if
@comments_allowed
&&
can?
(
current_user
,
:create_note
,
@project
)
=
link_to_new_diff_note
(
left
[
:line_code
],
'old'
)
=
link_to_new_diff_note
(
left
[
:line_code
],
'old'
)
%td
.line_content
{
class:
"parallel noteable_line #{left[:type]} #{left[:line_code]}"
,
"line_code"
=>
left
[
:line_code
]
}=
diff_line_content
(
left
[
:text
])
%td
.line_content
{
class:
"parallel noteable_line #{left[:type]} #{left[:line_code]}"
,
data:
{
"line_code"
=>
left
[
:line_code
]
}
}=
diff_line_content
(
left
[
:text
])
-
if
right
[
:type
]
==
'new'
-
if
right
[
:type
]
==
'new'
-
new_line_class
=
'new'
-
new_line_class
=
'new'
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
=
link_to
raw
(
right
[
:number
]),
"#
#{
new_line_code
}
"
,
id:
new_line_code
=
link_to
raw
(
right
[
:number
]),
"#
#{
new_line_code
}
"
,
id:
new_line_code
-
if
@comments_allowed
&&
can?
(
current_user
,
:create_note
,
@project
)
-
if
@comments_allowed
&&
can?
(
current_user
,
:create_note
,
@project
)
=
link_to_new_diff_note
(
right
[
:line_code
],
'new'
)
=
link_to_new_diff_note
(
right
[
:line_code
],
'new'
)
%td
.line_content.parallel
{
class:
"noteable_line #{new_line_class} #{new_line_code}"
,
"line_code"
=>
new_line_code
}=
diff_line_content
(
right
[
:text
])
%td
.line_content.parallel
{
class:
"noteable_line #{new_line_class} #{new_line_code}"
,
data:
{
"line_code"
=>
new_line_code
}
}=
diff_line_content
(
right
[
:text
])
-
if
@reply_allowed
-
if
@reply_allowed
-
comments_left
,
comments_right
=
organize_comments
(
left
[
:type
],
right
[
:type
],
left
[
:line_code
],
right
[
:line_code
])
-
comments_left
,
comments_right
=
organize_comments
(
left
[
:type
],
right
[
:type
],
left
[
:line_code
],
right
[
:line_code
])
...
...
app/views/projects/diffs/_text_file.html.haml
View file @
8dfad143
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
=
link_to_new_diff_note
(
line_code
)
=
link_to_new_diff_note
(
line_code
)
%td
.new_line
{
data:
{
linenumber:
line
.
new_pos
}}
%td
.new_line
{
data:
{
linenumber:
line
.
new_pos
}}
=
link_to
raw
(
type
==
"old"
?
" "
:
line
.
new_pos
),
"#
#{
line_code
}
"
,
id:
line_code
=
link_to
raw
(
type
==
"old"
?
" "
:
line
.
new_pos
),
"#
#{
line_code
}
"
,
id:
line_code
%td
.line_content
{
class:
"noteable_line #{type} #{line_code}"
,
"line_code"
=>
line_code
}=
diff_line_content
(
line
.
text
)
%td
.line_content
{
class:
"noteable_line #{type} #{line_code}"
,
data:
{
"line_code"
=>
line_code
}
}=
diff_line_content
(
line
.
text
)
-
if
@reply_allowed
-
if
@reply_allowed
-
comments
=
@line_notes
.
select
{
|
n
|
n
.
line_code
==
line_code
&&
n
.
active?
}.
sort_by
(
&
:created_at
)
-
comments
=
@line_notes
.
select
{
|
n
|
n
.
line_code
==
line_code
&&
n
.
active?
}.
sort_by
(
&
:created_at
)
...
...
lib/gitlab/diff/file.rb
View file @
8dfad143
...
@@ -18,7 +18,7 @@ module Gitlab
...
@@ -18,7 +18,7 @@ module Gitlab
end
end
def
highlighted_diff_lines
def
highlighted_diff_lines
Gitlab
::
Diff
::
Highlight
.
process_diff_lines
(
self
)
Gitlab
::
Diff
::
Highlight
.
new
(
self
).
highlight
end
end
def
mode_changed?
def
mode_changed?
...
...
lib/gitlab/diff/highlight.rb
View file @
8dfad143
...
@@ -6,59 +6,199 @@ module Gitlab
...
@@ -6,59 +6,199 @@ module Gitlab
delegate
:repository
,
:old_path
,
:new_path
,
:old_ref
,
:new_ref
,
delegate
:repository
,
:old_path
,
:new_path
,
:old_ref
,
:new_ref
,
to: :diff_file
,
prefix: :diff
to: :diff_file
,
prefix: :diff
# Apply syntax highlight to provided source code
def
initialize
(
diff_file
)
#
@diff_file
=
diff_file
# diff_file - an instance of Gitlab::Diff::File
@diff_lines
=
diff_file
.
diff_lines
#
@raw_lines
=
@diff_lines
.
map
(
&
:text
)
# Returns an Array with the processed items.
def
self
.
process_diff_lines
(
diff_file
)
processor
=
new
(
diff_file
)
processor
.
highlight
end
end
def
self
.
process_file
(
repository
,
ref
,
file_name
)
def
highlight
blob
=
repository
.
blob_at
(
ref
,
file_name
)
return
[]
if
@diff_lines
.
empty?
return
[]
unless
blob
Gitlab
::
Highlight
.
highlight
(
file_name
,
blob
.
data
).
lines
.
map!
(
&
:html_safe
)
find_inline_diffs
end
def
initialize
(
diff_file
)
process_lines
@diff_file
=
diff_file
@file_name
=
diff_file
.
new_path
@diff_lines
@lines
=
diff_file
.
diff_lines
end
end
def
highlight
private
return
[]
if
@lines
.
empty?
@lines
.
each_with_index
do
|
line
,
i
|
def
find_inline_diffs
line_prefix
=
line
.
text
.
match
(
/\A([+-])/
)
?
$1
:
' '
@inline_diffs
=
[]
local_edit_indexes
.
each
do
|
index
|
old_index
=
index
new_index
=
index
+
1
old_line
=
@raw_lines
[
old_index
][
1
..-
1
]
new_line
=
@raw_lines
[
new_index
][
1
..-
1
]
# Skip inline diff if empty line was replaced with content
next
if
old_line
==
""
lcp
=
longest_common_prefix
(
old_line
,
new_line
)
lcs
=
longest_common_suffix
(
old_line
,
new_line
)
old_diff_range
=
lcp
..
(
old_line
.
length
-
lcs
-
1
)
new_diff_range
=
lcp
..
(
new_line
.
length
-
lcs
-
1
)
@inline_diffs
[
old_index
]
=
old_diff_range
if
old_diff_range
.
begin
<=
old_diff_range
.
end
@inline_diffs
[
new_index
]
=
new_diff_range
if
new_diff_range
.
begin
<=
new_diff_range
.
end
end
end
def
process_lines
@diff_lines
.
each_with_index
do
|
diff_line
,
i
|
# ignore highlighting for "match" lines
# ignore highlighting for "match" lines
next
if
line
.
type
==
'match'
next
if
diff_
line
.
type
==
'match'
case
line
.
type
rich_line
=
highlight_line
(
diff_line
,
i
)
rich_line
=
mark_inline_diffs
(
rich_line
,
diff_line
,
i
)
diff_line
.
text
=
rich_line
.
html_safe
end
end
def
highlight_line
(
diff_line
,
index
)
line_prefix
=
line_prefixes
[
index
]
case
diff_line
.
type
when
'new'
,
nil
when
'new'
,
nil
highlighted_line
=
new_lines
[
line
.
new_pos
-
1
]
rich_line
=
new_lines
[
diff_
line
.
new_pos
-
1
]
when
'old'
when
'old'
highlighted_line
=
old_lines
[
line
.
old_pos
-
1
]
rich_line
=
old_lines
[
diff_
line
.
old_pos
-
1
]
end
end
# Only update text if line is found. This will prevent
# Only update text if line is found. This will prevent
# issues with submodules given the line only exists in diff content.
# issues with submodules given the line only exists in diff content.
line
.
text
=
highlighted_line
.
insert
(
0
,
line_prefix
).
html_safe
if
highlighted_line
rich_line
?
line_prefix
+
rich_line
:
diff_line
.
text
end
def
mark_inline_diffs
(
rich_line
,
diff_line
,
index
)
inline_diff
=
@inline_diffs
[
index
]
return
rich_line
unless
inline_diff
raw_line
=
diff_line
.
text
# Based on the prefixless versions
from
=
inline_diff
.
begin
+
1
to
=
inline_diff
.
end
+
1
position_mapping
=
map_character_positions
(
raw_line
,
rich_line
)
inline_diff_positions
=
position_mapping
[
from
..
to
]
marker_ranges
=
collapse_ranges
(
inline_diff_positions
)
offset
=
0
marker_ranges
.
each
do
|
range
|
offset
=
insert_around_range
(
rich_line
,
range
,
"<span class='idiff'>"
,
"</span>"
,
offset
)
end
rich_line
end
def
line_prefixes
@line_prefixes
||=
@raw_lines
.
map
{
|
line
|
line
.
match
(
/\A([+-])/
)
?
$1
:
' '
}
end
def
local_edit_indexes
@local_edit_indexes
||=
begin
joined_line_prefixes
=
"
#{
line_prefixes
.
join
}
"
offset
=
0
local_edit_indexes
=
[]
while
index
=
joined_line_prefixes
.
index
(
" -+ "
,
offset
)
local_edit_indexes
<<
index
offset
=
index
+
1
end
local_edit_indexes
end
end
def
map_character_positions
(
raw_line
,
rich_line
)
mapping
=
[]
raw_pos
=
0
rich_pos
=
0
(
0
..
raw_line
.
length
).
each
do
|
raw_pos
|
raw_char
=
raw_line
[
raw_pos
]
rich_char
=
rich_line
[
rich_pos
]
while
rich_char
==
'<'
until
rich_char
==
'>'
rich_pos
+=
1
rich_char
=
rich_line
[
rich_pos
]
end
rich_pos
+=
1
rich_char
=
rich_line
[
rich_pos
]
end
mapping
[
raw_pos
]
=
rich_pos
rich_pos
+=
1
end
end
@lines
mapping
end
end
def
old_lines
def
old_lines
@old_lines
||=
self
.
class
.
process_file
(
diff_repository
,
diff_old_ref
,
diff_old_path
)
@old_lines
||=
Gitlab
::
Highlight
.
highlight_lines
(
diff_repository
,
diff_old_ref
,
diff_old_path
)
end
end
def
new_lines
def
new_lines
@new_lines
||=
self
.
class
.
process_file
(
diff_repository
,
diff_new_ref
,
diff_new_path
)
@new_lines
||=
Gitlab
::
Highlight
.
highlight_lines
(
diff_repository
,
diff_new_ref
,
diff_new_path
)
end
def
longest_common_suffix
(
a
,
b
)
longest_common_prefix
(
a
.
reverse
,
b
.
reverse
)
end
def
longest_common_prefix
(
a
,
b
)
max_length
=
[
a
.
length
,
b
.
length
].
max
length
=
0
(
0
..
max_length
-
1
).
each
do
|
pos
|
old_char
=
a
[
pos
]
new_char
=
b
[
pos
]
break
if
old_char
!=
new_char
length
+=
1
end
length
end
def
collapse_ranges
(
positions
)
return
[]
if
positions
.
empty?
ranges
=
[]
start
=
prev
=
positions
[
0
]
range
=
start
..
prev
positions
[
1
..-
1
].
each
do
|
pos
|
if
pos
==
prev
+
1
range
=
start
..
pos
prev
=
pos
else
ranges
<<
range
start
=
prev
=
pos
range
=
start
..
prev
end
end
ranges
<<
range
ranges
end
def
insert_around_range
(
text
,
range
,
before
,
after
,
offset
=
0
)
from
=
range
.
begin
to
=
range
.
end
text
.
insert
(
offset
+
from
,
before
)
offset
+=
before
.
length
text
.
insert
(
offset
+
to
+
1
,
after
)
offset
+=
after
.
length
offset
end
end
end
end
end
end
...
...
lib/gitlab/highlight.rb
View file @
8dfad143
...
@@ -7,6 +7,13 @@ module Gitlab
...
@@ -7,6 +7,13 @@ module Gitlab
formatter
.
format
(
lexer
.
lex
(
blob_content
,
continue:
continue
)).
html_safe
formatter
.
format
(
lexer
.
lex
(
blob_content
,
continue:
continue
)).
html_safe
end
end
def
self
.
highlight_lines
(
repository
,
ref
,
file_name
)
blob
=
repository
.
blob_at
(
ref
,
file_name
)
return
[]
unless
blob
highlight
(
file_name
,
blob
.
data
).
lines
.
map!
(
&
:html_safe
)
end
private
private
def
self
.
rouge_formatter
(
options
=
{})
def
self
.
rouge_formatter
(
options
=
{})
...
...
spec/lib/gitlab/diff/highlight_spec.rb
View file @
8dfad143
...
@@ -51,9 +51,9 @@ describe Gitlab::Diff::Highlight, lib: true do
...
@@ -51,9 +51,9 @@ describe Gitlab::Diff::Highlight, lib: true do
end
end
end
end
describe
'.
process_file
'
do
describe
'.
highlight_lines
'
do
let
(
:lines
)
do
let
(
:lines
)
do
Gitlab
::
Diff
::
Highlight
.
process_file
(
project
.
repository
,
commit
.
id
,
'files/ruby/popen.rb'
)
Gitlab
::
Diff
::
Highlight
.
highlight_lines
(
project
.
repository
,
commit
.
id
,
'files/ruby/popen.rb'
)
end
end
it
'should properly highlight all the lines'
do
it
'should properly highlight all the lines'
do
...
...
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