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
9c8edcd6
Commit
9c8edcd6
authored
Sep 24, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
bc898829
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
260 additions
and
130 deletions
+260
-130
app/assets/javascripts/autosave.js
app/assets/javascripts/autosave.js
+2
-2
app/assets/javascripts/behaviors/requires_input.js
app/assets/javascripts/behaviors/requires_input.js
+1
-1
app/assets/javascripts/commit/image_file.js
app/assets/javascripts/commit/image_file.js
+6
-6
app/assets/javascripts/gl_dropdown.js
app/assets/javascripts/gl_dropdown.js
+13
-15
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+5
-10
app/assets/javascripts/lib/utils/text_markdown.js
app/assets/javascripts/lib/utils/text_markdown.js
+2
-2
app/assets/javascripts/line_highlighter.js
app/assets/javascripts/line_highlighter.js
+5
-5
app/assets/javascripts/namespace_select.js
app/assets/javascripts/namespace_select.js
+3
-3
app/assets/javascripts/network/branch_graph.js
app/assets/javascripts/network/branch_graph.js
+2
-2
app/assets/javascripts/new_branch_form.js
app/assets/javascripts/new_branch_form.js
+3
-3
app/assets/javascripts/notes.js
app/assets/javascripts/notes.js
+9
-11
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
...pts/pages/projects/graphs/show/stat_graph_contributors.js
+3
-3
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
...ges/projects/graphs/show/stat_graph_contributors_graph.js
+8
-13
app/assets/javascripts/pages/projects/network/network.js
app/assets/javascripts/pages/projects/network/network.js
+2
-2
app/assets/javascripts/project_find_file.js
app/assets/javascripts/project_find_file.js
+2
-2
app/assets/javascripts/right_sidebar.js
app/assets/javascripts/right_sidebar.js
+2
-2
app/assets/javascripts/search_autocomplete.js
app/assets/javascripts/search_autocomplete.js
+3
-3
app/assets/javascripts/users_select.js
app/assets/javascripts/users_select.js
+8
-9
changelogs/unreleased/jc-optimize-uri-type.yml
changelogs/unreleased/jc-optimize-uri-type.yml
+5
-0
lib/banzai/filter/relative_link_filter.rb
lib/banzai/filter/relative_link_filter.rb
+96
-20
lib/gitlab/gitaly_client/blob_service.rb
lib/gitlab/gitaly_client/blob_service.rb
+34
-0
spec/features/boards/boards_spec.rb
spec/features/boards/boards_spec.rb
+6
-0
spec/javascripts/line_highlighter_spec.js
spec/javascripts/line_highlighter_spec.js
+14
-14
spec/lib/banzai/filter/relative_link_filter_spec.rb
spec/lib/banzai/filter/relative_link_filter_spec.rb
+26
-2
No files found.
app/assets/javascripts/autosave.js
View file @
9c8edcd6
/* eslint-disable no-param-reassign,
prefer-template,
no-void, consistent-return */
/* eslint-disable no-param-reassign, no-void, consistent-return */
import
AccessorUtilities
from
'
./lib/utils/accessor
'
;
...
...
@@ -10,7 +10,7 @@ export default class Autosave {
if
(
key
.
join
!=
null
)
{
key
=
key
.
join
(
'
/
'
);
}
this
.
key
=
'
autosave/
'
+
key
;
this
.
key
=
`autosave/
${
key
}
`
;
this
.
field
.
data
(
'
autosave
'
,
this
);
this
.
restore
();
this
.
field
.
on
(
'
input
'
,
()
=>
this
.
save
());
...
...
app/assets/javascripts/behaviors/requires_input.js
View file @
9c8edcd6
...
...
@@ -26,7 +26,7 @@ $.fn.requiresInput = function requiresInput() {
const
values
=
_
.
map
(
$
(
fieldSelector
,
$form
),
field
=>
field
.
value
);
// Disable the button if any required fields are empty
if
(
values
.
length
&&
_
.
any
(
values
,
_
.
isEmpty
))
{
if
(
values
.
length
&&
_
.
some
(
values
,
_
.
isEmpty
))
{
$button
.
disable
();
}
else
{
$button
.
enable
();
...
...
app/assets/javascripts/commit/image_file.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, no-else-return, consistent-return,
prefer-template,
one-var, no-return-assign, no-unused-expressions, no-sequences */
/* eslint-disable func-names, no-var, no-else-return, consistent-return, one-var, no-return-assign, no-unused-expressions, no-sequences */
import
$
from
'
jquery
'
;
...
...
@@ -49,13 +49,13 @@ export default class ImageFile {
activateViewMode
(
viewMode
)
{
$
(
'
.view-modes-menu li
'
,
this
.
file
)
.
removeClass
(
'
active
'
)
.
filter
(
'
.
'
+
viewMode
)
.
filter
(
`.
${
viewMode
}
`
)
.
addClass
(
'
active
'
);
return
$
(
'
.view:visible:not(.
'
+
viewMode
+
'
)
'
,
this
.
file
).
fadeOut
(
return
$
(
`.view:visible:not(.
${
viewMode
}
)`
,
this
.
file
).
fadeOut
(
200
,
(
function
(
_this
)
{
return
function
()
{
$
(
'
.view.
'
+
viewMode
,
_this
.
file
).
fadeIn
(
200
);
$
(
`.view.
${
viewMode
}
`
,
_this
.
file
).
fadeIn
(
200
);
return
_this
.
initView
(
viewMode
);
};
})(
this
),
...
...
@@ -139,8 +139,8 @@ export default class ImageFile {
}
});
return
_this
.
requestImageInfo
(
$
(
'
img
'
,
wrap
),
(
width
,
height
)
=>
{
$
(
'
.image-info .meta-width
'
,
wrap
).
text
(
width
+
'
px
'
);
$
(
'
.image-info .meta-height
'
,
wrap
).
text
(
height
+
'
px
'
);
$
(
'
.image-info .meta-width
'
,
wrap
).
text
(
`
${
width
}
px`
);
$
(
'
.image-info .meta-height
'
,
wrap
).
text
(
`
${
height
}
px`
);
return
$
(
'
.image-info
'
,
wrap
).
removeClass
(
'
hide
'
);
});
};
...
...
app/assets/javascripts/gl_dropdown.js
View file @
9c8edcd6
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-shadow, no-cond-assign, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return,
prefer-template,
no-param-reassign, no-loop-func */
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-shadow, no-cond-assign, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, no-param-reassign, no-loop-func */
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
...
...
@@ -272,7 +272,7 @@ GitLabDropdown = (function() {
NON_SELECTABLE_CLASSES
=
'
.divider, .separator, .dropdown-header, .dropdown-menu-empty-item
'
;
SELECTABLE_CLASSES
=
'
.dropdown-content li:not(
'
+
NON_SELECTABLE_CLASSES
+
'
, .option-hidden)
'
;
SELECTABLE_CLASSES
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
, .option-hidden)`
;
CURSOR_SELECT_SCROLL_PADDING
=
5
;
...
...
@@ -359,9 +359,9 @@ GitLabDropdown = (function() {
instance
:
this
,
elements
:
(
function
(
_this
)
{
return
function
()
{
selector
=
'
.dropdown-content li:not(
'
+
NON_SELECTABLE_CLASSES
+
'
)
'
;
selector
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
)`
;
if
(
_this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one
'
+
selector
;
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
return
$
(
selector
,
this
.
instance
.
dropdown
);
};
...
...
@@ -377,7 +377,7 @@ GitLabDropdown = (function() {
if
(
_this
.
filterInput
.
val
()
!==
''
)
{
selector
=
SELECTABLE_CLASSES
;
if
(
_this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one
'
+
selector
;
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
if
(
$
(
_this
.
el
).
is
(
'
input
'
))
{
currentIndex
=
-
1
;
...
...
@@ -693,7 +693,7 @@ GitLabDropdown = (function() {
.
split
(
''
)
.
map
((
character
,
i
)
=>
{
if
(
indexOf
.
call
(
occurrences
,
i
)
!==
-
1
)
{
return
'
<b>
'
+
character
+
'
</b>
'
;
return
`<b>
${
character
}
</b>`
;
}
else
{
return
character
;
}
...
...
@@ -738,9 +738,7 @@ GitLabDropdown = (function() {
}
else
if
(
value
!=
null
)
{
field
=
this
.
dropdown
.
parent
()
.
find
(
"
input[name='
"
+
fieldName
+
"
'][value='
"
+
value
.
toString
().
replace
(
/'/g
,
"
\\
'
"
)
+
"
']
"
,
);
.
find
(
`input[name='
${
fieldName
}
'][value='
${
value
.
toString
().
replace
(
/'/g
,
"
\\
'
"
)}
']`
);
}
if
(
this
.
options
.
isSelectable
&&
!
this
.
options
.
isSelectable
(
selectedObject
,
el
))
{
...
...
@@ -766,11 +764,11 @@ GitLabDropdown = (function() {
}
else
{
isMarking
=
true
;
if
(
!
this
.
options
.
multiSelect
||
el
.
hasClass
(
'
dropdown-clear-active
'
))
{
this
.
dropdown
.
find
(
'
.
'
+
ACTIVE_CLASS
).
removeClass
(
ACTIVE_CLASS
);
this
.
dropdown
.
find
(
`.
${
ACTIVE_CLASS
}
`
).
removeClass
(
ACTIVE_CLASS
);
if
(
!
isInput
)
{
this
.
dropdown
.
parent
()
.
find
(
"
input[name='
"
+
fieldName
+
"
']
"
)
.
find
(
`input[name='
${
fieldName
}
']`
)
.
remove
();
}
}
...
...
@@ -809,7 +807,7 @@ GitLabDropdown = (function() {
var
$input
;
// Create hidden input for form
if
(
single
)
{
$
(
'
input[name="
'
+
fieldName
+
'
"]
'
).
remove
();
$
(
`input[name="
${
fieldName
}
"]`
).
remove
();
}
$input
=
$
(
'
<input>
'
)
...
...
@@ -837,12 +835,12 @@ GitLabDropdown = (function() {
var
$el
,
selector
;
// If we pass an option index
if
(
typeof
index
!==
'
undefined
'
)
{
selector
=
SELECTABLE_CLASSES
+
'
:eq(
'
+
index
+
'
) a
'
;
selector
=
`
${
SELECTABLE_CLASSES
}
:eq(
${
index
}
) a`
;
}
else
{
selector
=
'
.dropdown-content .is-focused
'
;
}
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one
'
+
selector
;
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
// simulate a click on the first link
$el
=
$
(
selector
,
this
.
dropdown
);
...
...
@@ -861,7 +859,7 @@ GitLabDropdown = (function() {
ARROW_KEY_CODES
=
[
38
,
40
];
selector
=
SELECTABLE_CLASSES
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one
'
+
selector
;
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
return
$
(
'
body
'
).
on
(
'
keydown
'
,
...
...
app/assets/javascripts/labels_select.js
View file @
9c8edcd6
/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, one-var,
prefer-template,
no-new, consistent-return, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, one-var, no-new, consistent-return, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
/* global Issuable */
/* global ListLabel */
...
...
@@ -70,7 +70,7 @@ export default class LabelsSelect {
$loading
=
$block
.
find
(
'
.block-loading
'
).
fadeOut
();
fieldName
=
$dropdown
.
data
(
'
fieldName
'
);
initialSelected
=
$selectbox
.
find
(
'
input[name="
'
+
$dropdown
.
data
(
'
fieldName
'
)
+
'
"]
'
)
.
find
(
`input[name="
${
$dropdown
.
data
(
'
fieldName
'
)}
"]`
)
.
map
(
function
()
{
return
this
.
value
;
})
...
...
@@ -92,7 +92,7 @@ export default class LabelsSelect {
var
data
,
selected
;
selected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
fieldName
+
"
']
"
)
.
find
(
`input[name='
${
fieldName
}
']`
)
.
map
(
function
()
{
return
this
.
value
;
})
...
...
@@ -267,11 +267,7 @@ export default class LabelsSelect {
if
(
$form
.
find
(
"
input[type='hidden'][name='
"
+
this
.
fieldName
+
"
'][value='
"
+
dropdownValue
+
"
']
"
,
`input[type='hidden'][name='
${
this
.
fieldName
}
'][value='
${
dropdownValue
}
']`
,
).
length
)
{
selectedClass
.
push
(
'
is-active
'
);
...
...
@@ -284,8 +280,7 @@ export default class LabelsSelect {
}
if
(
label
.
color
)
{
colorEl
=
"
<span class='dropdown-label-box' style='background:
"
+
label
.
color
+
"
'></span>
"
;
colorEl
=
`<span class='dropdown-label-box' style='background:
${
label
.
color
}
'></span>`
;
}
else
{
colorEl
=
''
;
}
...
...
app/assets/javascripts/lib/utils/text_markdown.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, no-param-reassign, one-var, operator-assignment, no-else-return,
prefer-template,
consistent-return */
/* eslint-disable func-names, no-var, no-param-reassign, one-var, operator-assignment, no-else-return, consistent-return */
import
$
from
'
jquery
'
;
import
{
insertText
}
from
'
~/lib/utils/common_utils
'
;
...
...
@@ -237,7 +237,7 @@ export function insertMarkdownText({
}
if
(
removedFirstNewLine
)
{
textToInsert
=
'
\n
'
+
textToInsert
;
textToInsert
=
`\n
${
textToInsert
}
`
;
}
if
(
removedLastNewLine
)
{
...
...
app/assets/javascripts/line_highlighter.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, no-underscore-dangle, no-param-reassign,
prefer-template,
consistent-return, one-var, no-else-return */
/* eslint-disable func-names, no-var, no-underscore-dangle, no-param-reassign, consistent-return, one-var, no-else-return */
import
$
from
'
jquery
'
;
...
...
@@ -106,7 +106,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
};
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
return
$
(
'
.
'
+
this
.
highlightLineClass
).
removeClass
(
this
.
highlightLineClass
);
return
$
(
`.
${
this
.
highlightLineClass
}
`
).
removeClass
(
this
.
highlightLineClass
);
};
// Convert a URL hash String into line numbers
...
...
@@ -137,7 +137,7 @@ LineHighlighter.prototype.hashToRange = function(hash) {
//
// lineNumber - Line number to highlight
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
return
$
(
'
#LC
'
+
lineNumber
).
addClass
(
this
.
highlightLineClass
);
return
$
(
`#LC
${
lineNumber
}
`
).
addClass
(
this
.
highlightLineClass
);
};
// Highlight all lines within a range
...
...
@@ -162,9 +162,9 @@ LineHighlighter.prototype.highlightRange = function(range) {
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
var
hash
;
if
(
lastLineNumber
)
{
hash
=
'
#L
'
+
firstLineNumber
+
'
-
'
+
lastLineNumber
;
hash
=
`#L
${
firstLineNumber
}
-
${
lastLineNumber
}
`
;
}
else
{
hash
=
'
#L
'
+
firstLineNumber
;
hash
=
`#L
${
firstLineNumber
}
`
;
}
this
.
_hash
=
hash
;
return
this
.
__setLocationHash__
(
hash
);
...
...
app/assets/javascripts/namespace_select.js
View file @
9c8edcd6
/* eslint-disable no-else-return
, prefer-template
*/
/* eslint-disable no-else-return */
import
$
from
'
jquery
'
;
import
'
~/gl_dropdown
'
;
...
...
@@ -24,7 +24,7 @@ export default class NamespaceSelect {
if
(
selected
.
id
==
null
)
{
return
selected
.
text
;
}
else
{
return
selected
.
kind
+
'
:
'
+
selected
.
full_path
;
return
`
${
selected
.
kind
}
:
${
selected
.
full_path
}
`
;
}
},
data
(
term
,
dataCallback
)
{
...
...
@@ -44,7 +44,7 @@ export default class NamespaceSelect {
if
(
namespace
.
id
==
null
)
{
return
namespace
.
text
;
}
else
{
return
namespace
.
kind
+
'
:
'
+
namespace
.
full_path
;
return
`
${
namespace
.
kind
}
:
${
namespace
.
full_path
}
`
;
}
},
renderRow
:
this
.
renderRow
,
...
...
app/assets/javascripts/network/branch_graph.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, one-var, no-loop-func, consistent-return,
prefer-template,
camelcase */
/* eslint-disable func-names, no-var, one-var, no-loop-func, consistent-return, camelcase */
import
$
from
'
jquery
'
;
import
{
__
}
from
'
../locale
'
;
...
...
@@ -223,7 +223,7 @@ export default (function() {
shortrefs
=
commit
.
refs
;
// Truncate if longer than 15 chars
if
(
shortrefs
.
length
>
17
)
{
shortrefs
=
shortrefs
.
substr
(
0
,
15
)
+
'
…
'
;
shortrefs
=
`
${
shortrefs
.
substr
(
0
,
15
)}
…`
;
}
text
=
r
.
text
(
x
+
4
,
y
,
shortrefs
).
attr
({
'
text-anchor
'
:
'
start
'
,
...
...
app/assets/javascripts/new_branch_form.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, one-var, consistent-return, no-return-assign,
prefer-template,
no-shadow, no-else-return, @gitlab/i18n/no-non-i18n-strings */
/* eslint-disable func-names, no-var, one-var, consistent-return, no-return-assign, no-shadow, no-else-return, @gitlab/i18n/no-non-i18n-strings */
import
$
from
'
jquery
'
;
import
RefSelectDropdown
from
'
./ref_select_dropdown
'
;
...
...
@@ -70,10 +70,10 @@ export default class NewBranchForm {
case
!
/
\/{2,}
/g
.
test
(
value
):
return
'
consecutive slashes
'
;
default
:
return
"
'
"
+
value
+
"
'
"
;
return
`'
${
value
}
'`
;
}
});
return
restriction
.
prefix
+
'
'
+
formatted
.
join
(
restriction
.
conjunction
)
;
return
`
${
restriction
.
prefix
}
${
formatted
.
join
(
restriction
.
conjunction
)}
`
;
};
validator
=
(
function
(
_this
)
{
return
function
(
errors
,
restriction
)
{
...
...
app/assets/javascripts/notes.js
View file @
9c8edcd6
/* eslint-disable no-restricted-properties, func-names, no-var, camelcase,
no-unused-expressions, one-var, default-case,
prefer-template,
consistent-return, no-alert, no-return-assign,
consistent-return, no-alert, no-return-assign,
no-param-reassign, no-else-return, vars-on-top,
no-shadow, no-useless-escape, class-methods-use-this */
...
...
@@ -490,7 +490,7 @@ export default class Notes {
diffAvatarContainer
=
row
.
prevAll
(
'
.line_holder
'
)
.
first
()
.
find
(
'
.js-avatar-container.
'
+
lineType
+
'
_line
'
);
.
find
(
`.js-avatar-container.
${
lineType
}
_line`
);
// is this the first note of discussion?
discussionContainer
=
$
(
`.notes[data-discussion-id="
${
noteEntity
.
discussion_id
}
"]`
);
if
(
!
discussionContainer
.
length
)
{
...
...
@@ -506,16 +506,14 @@ export default class Notes {
}
else
{
// Merge new discussion HTML in
var
$notes
=
$discussion
.
find
(
`.notes[data-discussion-id="
${
noteEntity
.
discussion_id
}
"]`
);
var
contentContainerClass
=
'
.
'
+
$notes
.
closest
(
'
.notes-content
'
)
.
attr
(
'
class
'
)
.
split
(
'
'
)
.
join
(
'
.
'
);
var
contentContainerClass
=
$notes
.
closest
(
'
.notes-content
'
)
.
attr
(
'
class
'
)
.
split
(
'
'
)
.
join
(
'
.
'
);
row
.
find
(
contentContainerClass
+
'
.content
'
)
.
find
(
`.
${
contentContainerClass
}
.content`
)
.
append
(
$notes
.
closest
(
'
.content
'
).
children
());
}
}
else
{
...
...
@@ -722,7 +720,7 @@ export default class Notes {
this
.
revertNoteEditForm
(
$targetNote
);
$noteEntityEl
.
renderGFM
();
// Find the note's `li` element by ID and replace it with the updated HTML
$note_li
=
$
(
'
.note-row-
'
+
noteEntity
.
id
);
$note_li
=
$
(
`.note-row-
${
noteEntity
.
id
}
`
);
$note_li
.
replaceWith
(
$noteEntityEl
);
this
.
setupNewNote
(
$noteEntityEl
);
...
...
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, one-var, camelcase, no-param-reassign,
prefer-template,
no-return-assign */
/* eslint-disable func-names, no-var, one-var, camelcase, no-param-reassign, no-return-assign */
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
...
...
@@ -66,8 +66,8 @@ export default (function() {
class
:
'
person
'
,
style
:
'
display: block;
'
,
});
author_name
=
$
(
'
<h4>
'
+
author
.
author_name
+
'
</h4>
'
);
author_email
=
$
(
'
<p class="graph-author-email">
'
+
author
.
author_email
+
'
</p>
'
);
author_name
=
$
(
`<h4>
${
author
.
author_name
}
</h4>`
);
author_email
=
$
(
`<p class="graph-author-email">
${
author
.
author_email
}
</p>`
);
author_commit_info_span
=
$
(
'
<span/>
'
,
{
class
:
'
commits
'
,
});
...
...
app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
View file @
9c8edcd6
/* eslint-disable func-names, no-restricted-syntax, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, no-return-assign,
prefer-template,
no-else-return, no-shadow */
/* eslint-disable func-names, no-restricted-syntax, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, no-return-assign, no-else-return, no-shadow */
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
...
...
@@ -118,14 +118,11 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph
.
prototype
.
draw_x_axis
=
function
()
{
return
(
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
class
'
,
'
x axis
'
)
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.
attr
(
'
transform
'
,
'
translate(0,
'
+
this
.
height
+
'
)
'
)
.
call
(
this
.
x_axis
)
);
return
this
.
svg
.
append
(
'
g
'
)
.
attr
(
'
class
'
,
'
x axis
'
)
.
attr
(
'
transform
'
,
`translate(0,
${
this
.
height
}
)`
)
.
call
(
this
.
x_axis
);
};
ContributorsGraph
.
prototype
.
draw_y_axis
=
function
()
{
...
...
@@ -200,8 +197,7 @@ export const ContributorsMasterGraph = (function(superClass) {
.
attr
(
'
height
'
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
'
class
'
,
'
tint-box
'
)
.
append
(
'
g
'
)
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.
attr
(
'
transform
'
,
'
translate(
'
+
this
.
MARGIN
.
left
+
'
,
'
+
this
.
MARGIN
.
top
+
'
)
'
);
.
attr
(
'
transform
'
,
`translate(
${
this
.
MARGIN
.
left
}
,
${
this
.
MARGIN
.
top
}
)`
);
return
this
.
svg
;
};
...
...
@@ -348,8 +344,7 @@ export const ContributorsAuthorGraph = (function(superClass) {
.
attr
(
'
height
'
,
this
.
height
+
this
.
MARGIN
.
top
+
this
.
MARGIN
.
bottom
)
.
attr
(
'
class
'
,
'
spark
'
)
.
append
(
'
g
'
)
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.
attr
(
'
transform
'
,
'
translate(
'
+
this
.
MARGIN
.
left
+
'
,
'
+
this
.
MARGIN
.
top
+
'
)
'
);
.
attr
(
'
transform
'
,
`translate(
${
this
.
MARGIN
.
left
}
,
${
this
.
MARGIN
.
top
}
)`
);
return
this
.
svg
;
};
...
...
app/assets/javascripts/pages/projects/network/network.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var
, prefer-template
*/
/* eslint-disable func-names, no-var */
import
$
from
'
jquery
'
;
import
BranchGraph
from
'
../../../network/branch_graph
'
;
...
...
@@ -14,7 +14,7 @@ export default (function() {
this
.
branch_graph
=
new
BranchGraph
(
$
(
'
.network-graph
'
),
opts
);
vph
=
$
(
window
).
height
()
-
250
;
$
(
'
.network-graph
'
).
css
({
height
:
vph
+
'
px
'
,
height
:
`
${
vph
}
px`
,
});
}
...
...
app/assets/javascripts/project_find_file.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, consistent-return, one-var, no-cond-assign,
prefer-template,
no-return-assign */
/* eslint-disable func-names, no-var, consistent-return, one-var, no-cond-assign, no-return-assign */
import
$
from
'
jquery
'
;
import
fuzzaldrinPlus
from
'
fuzzaldrin-plus
'
;
...
...
@@ -112,7 +112,7 @@ export default class ProjectFindFile {
if
(
searchText
)
{
matches
=
fuzzaldrinPlus
.
match
(
filePath
,
searchText
);
}
blobItemUrl
=
this
.
options
.
blobUrlTemplate
+
'
/
'
+
encodeURIComponent
(
filePath
)
;
blobItemUrl
=
`
${
this
.
options
.
blobUrlTemplate
}
/
${
encodeURIComponent
(
filePath
)}
`
;
html
=
ProjectFindFile
.
makeHtml
(
filePath
,
matches
,
blobItemUrl
);
results
.
push
(
this
.
element
.
find
(
'
.tree-table > tbody
'
).
append
(
html
));
}
...
...
app/assets/javascripts/right_sidebar.js
View file @
9c8edcd6
/* eslint-disable func-names, no-var, consistent-return, one-var,
prefer-template,
no-else-return, no-param-reassign */
/* eslint-disable func-names, no-var, consistent-return, one-var, no-else-return, no-param-reassign */
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
...
...
@@ -247,7 +247,7 @@ Sidebar.prototype.isOpen = function() {
};
Sidebar
.
prototype
.
getBlock
=
function
(
name
)
{
return
this
.
sidebar
.
find
(
'
.block.
'
+
name
);
return
this
.
sidebar
.
find
(
`.block.
${
name
}
`
);
};
export
default
Sidebar
;
app/assets/javascripts/search_autocomplete.js
View file @
9c8edcd6
/* eslint-disable no-return-assign, one-var, no-var, consistent-return,
prefer-template,
class-methods-use-this, no-lonely-if, vars-on-top */
/* eslint-disable no-return-assign, one-var, no-var, consistent-return, class-methods-use-this, no-lonely-if, vars-on-top */
import
$
from
'
jquery
'
;
import
{
escape
,
throttle
}
from
'
underscore
'
;
...
...
@@ -416,7 +416,7 @@ export class SearchAutocomplete {
inputs
=
Object
.
keys
(
this
.
originalState
);
for
(
i
=
0
,
len
=
inputs
.
length
;
i
<
len
;
i
+=
1
)
{
input
=
inputs
[
i
];
this
.
getElement
(
'
#
'
+
input
).
val
(
this
.
originalState
[
input
]);
this
.
getElement
(
`#
${
input
}
`
).
val
(
this
.
originalState
[
input
]);
}
}
...
...
@@ -426,7 +426,7 @@ export class SearchAutocomplete {
results
=
[];
for
(
i
=
0
,
len
=
inputs
.
length
;
i
<
len
;
i
+=
1
)
{
input
=
inputs
[
i
];
results
.
push
(
this
.
getElement
(
'
#
'
+
input
).
val
(
''
));
results
.
push
(
this
.
getElement
(
`#
${
input
}
`
).
val
(
''
));
}
return
results
;
}
...
...
app/assets/javascripts/users_select.js
View file @
9c8edcd6
/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, consistent-return, no-shadow, no-else-return, no-self-compare,
prefer-template,
no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */
/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, consistent-return, no-shadow, no-else-return, no-self-compare, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */
/* global Issuable */
/* global emitSidebarEvent */
...
...
@@ -428,8 +428,7 @@ function UsersSelect(currentUser, els, options = {}) {
const
isActive
=
$el
.
hasClass
(
'
is-active
'
);
const
previouslySelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
'][value!=0]
"
);
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value!=0]`
);
// Enables support for limiting the number of users selected
// Automatically removes the first on the list if more users are selected
...
...
@@ -448,7 +447,7 @@ function UsersSelect(currentUser, els, options = {}) {
// Remove unassigned selection (if it was previously selected)
const
unassignedSelected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
'][value=0]
"
);
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=0]`
);
if
(
unassignedSelected
)
{
unassignedSelected
.
remove
();
...
...
@@ -502,7 +501,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
else
if
(
!
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
selected
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
$dropdown
.
data
(
'
fieldName
'
)
+
"
']
"
)
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
']`
)
.
val
();
return
assignTo
(
selected
);
}
...
...
@@ -544,7 +543,7 @@ function UsersSelect(currentUser, els, options = {}) {
updateLabel
:
$dropdown
.
data
(
'
dropdownTitle
'
),
renderRow
(
user
)
{
var
avatar
,
img
,
username
;
username
=
user
.
username
?
'
@
'
+
user
.
username
:
''
;
username
=
user
.
username
?
`@
${
user
.
username
}
`
:
''
;
avatar
=
user
.
avatar_url
?
user
.
avatar_url
:
gon
.
default_avatar_url
;
let
selected
=
false
;
...
...
@@ -555,7 +554,7 @@ function UsersSelect(currentUser, els, options = {}) {
const
{
fieldName
}
=
this
;
const
field
=
$dropdown
.
closest
(
'
.selectbox
'
)
.
find
(
"
input[name='
"
+
fieldName
+
"
'][value='
"
+
user
.
id
+
"
']
"
);
.
find
(
`input[name='
${
fieldName
}
'][value='
${
user
.
id
}
']`
);
if
(
field
.
length
)
{
selected
=
true
;
...
...
@@ -571,7 +570,7 @@ function UsersSelect(currentUser, els, options = {}) {
)}
</a></li>`
;
}
else
{
// 0 margin, because it's now handled by a wrapper
img
=
"
<img src='
"
+
avatar
+
"
' class='avatar avatar-inline m-0' width='32' />
"
;
img
=
`<img src='
${
avatar
}
' class='avatar avatar-inline m-0' width='32' />`
;
}
return
_this
.
renderRow
(
options
.
issuableType
,
user
,
selected
,
username
,
img
);
...
...
@@ -715,7 +714,7 @@ UsersSelect.prototype.formatResult = function(user) {
${
_
.
escape
(
user
.
name
)}
</div>
<div class='user-username dropdown-menu-user-username text-secondary'>
${
!
user
.
invite
?
'
@
'
+
_
.
escape
(
user
.
username
)
:
''
}
${
!
user
.
invite
?
`@
${
_
.
escape
(
user
.
username
)}
`
:
''
}
</div>
</div>
</div>
...
...
changelogs/unreleased/jc-optimize-uri-type.yml
0 → 100644
View file @
9c8edcd6
---
title
:
Use GetBlobs RPC for uri type
merge_request
:
16824
author
:
type
:
performance
lib/banzai/filter/relative_link_filter.rb
View file @
9c8edcd6
...
...
@@ -20,16 +20,12 @@ module Banzai
def
call
return
doc
if
context
[
:system_note
]
@uri_types
=
{}
clear_memoization
(
:linkable_files
)
doc
.
search
(
'a:not(.gfm)'
).
each
do
|
el
|
process_link_attr
el
.
attribute
(
'href'
)
end
load_uri_types
doc
.
css
(
'img, video'
).
each
do
|
el
|
process_link_attr
el
.
attribute
(
'src'
)
process_link_attr
el
.
attribute
(
'data-src'
)
linkable_attributes
.
each
do
|
attr
|
process_link_attr
(
attr
)
end
doc
...
...
@@ -37,16 +33,81 @@ module Banzai
protected
def
load_uri_types
return
unless
linkable_files?
return
{}
unless
repository
clear_memoization
(
:linkable_attributes
)
@uri_types
=
request_path
.
present?
?
get_uri_types
([
request_path
])
:
{}
paths
=
linkable_attributes
.
flat_map
do
|
attr
|
[
get_uri
(
attr
).
to_s
,
relative_file_path
(
get_uri
(
attr
))]
end
paths
.
reject!
(
&
:blank?
)
paths
.
uniq!
@uri_types
.
merge!
(
get_uri_types
(
paths
))
end
def
linkable_files?
strong_memoize
(
:linkable_files
)
do
context
[
:project_wiki
].
nil?
&&
repository
.
try
(
:exists?
)
&&
!
repository
.
empty?
end
end
def
process_link_attr
(
html_attr
)
return
if
html_attr
.
blank?
return
if
html_attr
.
value
.
start_with?
(
'//'
)
def
linkable_attributes
strong_memoize
(
:linkable_attributes
)
do
attrs
=
[]
attrs
+=
doc
.
search
(
'a:not(.gfm)'
).
map
do
|
el
|
el
.
attribute
(
'href'
)
end
attrs
+=
doc
.
search
(
'img, video'
).
flat_map
do
|
el
|
[
el
.
attribute
(
'src'
),
el
.
attribute
(
'data-src'
)]
end
attrs
.
reject
do
|
attr
|
attr
.
blank?
||
attr
.
value
.
start_with?
(
'//'
)
end
end
end
def
get_uri_types
(
paths
)
return
{}
if
paths
.
empty?
uri_types
=
Hash
[
paths
.
collect
{
|
name
|
[
name
,
nil
]
}]
get_blob_types
(
paths
).
each
do
|
name
,
type
|
if
type
==
:blob
blob
=
::
Blob
.
decorate
(
Gitlab
::
Git
::
Blob
.
new
(
name:
name
),
project
)
uri_types
[
name
]
=
blob
.
image?
||
blob
.
video?
?
:raw
:
:blob
else
uri_types
[
name
]
=
type
end
end
uri_types
end
def
get_blob_types
(
paths
)
revision_paths
=
paths
.
collect
do
|
path
|
[
current_commit
.
sha
,
path
.
chomp
(
"/"
)]
end
Gitlab
::
GitalyClient
::
BlobService
.
new
(
repository
).
get_blob_types
(
revision_paths
,
1
)
end
def
get_uri
(
html_attr
)
uri
=
URI
(
html_attr
.
value
)
uri
if
uri
.
relative?
&&
uri
.
path
.
present?
rescue
URI
::
Error
,
Addressable
::
URI
::
InvalidURIError
end
def
process_link_attr
(
html_attr
)
if
html_attr
.
value
.
start_with?
(
'/uploads/'
)
process_link_to_upload_attr
(
html_attr
)
elsif
linkable_files?
&&
repo_visible_to_user?
...
...
@@ -81,6 +142,7 @@ module Banzai
def
process_link_to_repository_attr
(
html_attr
)
uri
=
URI
(
html_attr
.
value
)
if
uri
.
relative?
&&
uri
.
path
.
present?
html_attr
.
value
=
rebuild_relative_uri
(
uri
).
to_s
end
...
...
@@ -89,7 +151,7 @@ module Banzai
end
def
rebuild_relative_uri
(
uri
)
file_path
=
relative_file_path
(
uri
)
file_path
=
nested_file_path_if_exists
(
uri
)
uri
.
path
=
[
relative_url_root
,
...
...
@@ -102,13 +164,29 @@ module Banzai
uri
end
def
relative_file_path
(
uri
)
path
=
Addressable
::
URI
.
unescape
(
uri
.
path
).
delete
(
"
\0
"
)
request_path
=
Addressable
::
URI
.
unescape
(
context
[
:requested_path
]
)
nested_path
=
build_relative_path
(
path
,
request_path
)
def
nested_file_path_if_exists
(
uri
)
path
=
cleaned_file_path
(
uri
)
nested_path
=
relative_file_path
(
uri
)
file_exists?
(
nested_path
)
?
nested_path
:
path
end
def
cleaned_file_path
(
uri
)
Addressable
::
URI
.
unescape
(
uri
.
path
).
delete
(
"
\0
"
).
chomp
(
"/"
)
end
def
relative_file_path
(
uri
)
return
if
uri
.
nil?
build_relative_path
(
cleaned_file_path
(
uri
),
request_path
)
end
def
request_path
return
unless
context
[
:requested_path
]
Addressable
::
URI
.
unescape
(
context
[
:requested_path
]).
chomp
(
"/"
)
end
# Convert a relative path into its correct location based on the currently
# requested path
#
...
...
@@ -136,6 +214,7 @@ module Banzai
return
path
[
1
..-
1
]
if
path
.
start_with?
(
'/'
)
parts
=
request_path
.
split
(
'/'
)
parts
.
pop
if
uri_type
(
request_path
)
!=
:tree
path
.
sub!
(
%r{
\A\.
/}
,
''
)
...
...
@@ -149,14 +228,11 @@ module Banzai
end
def
file_exists?
(
path
)
path
.
present?
&&
!!
uri_type
(
path
)
path
.
present?
&&
uri_type
(
path
).
present?
end
def
uri_type
(
path
)
# https://gitlab.com/gitlab-org/gitlab-foss/issues/58657
Gitlab
::
GitalyClient
.
allow_n_plus_1_calls
do
@uri_types
[
path
]
||=
current_commit
.
uri_type
(
path
)
end
@uri_types
[
path
]
==
:unknown
?
""
:
@uri_types
[
path
]
end
def
current_commit
...
...
lib/gitlab/gitaly_client/blob_service.rb
View file @
9c8edcd6
...
...
@@ -76,6 +76,30 @@ module Gitlab
GitalyClient
::
BlobsStitcher
.
new
(
response
)
end
def
get_blob_types
(
revision_paths
,
limit
=
-
1
)
return
{}
if
revision_paths
.
empty?
request_revision_paths
=
revision_paths
.
map
do
|
rev
,
path
|
Gitaly
::
GetBlobsRequest
::
RevisionPath
.
new
(
revision:
rev
,
path:
encode_binary
(
path
))
end
request
=
Gitaly
::
GetBlobsRequest
.
new
(
repository:
@gitaly_repo
,
revision_paths:
request_revision_paths
,
limit:
limit
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_blobs
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
map_blob_types
(
response
)
end
def
get_new_lfs_pointers
(
revision
,
limit
,
not_in
,
dynamic_timeout
=
nil
)
request
=
Gitaly
::
GetNewLFSPointersRequest
.
new
(
repository:
@gitaly_repo
,
...
...
@@ -132,6 +156,16 @@ module Gitlab
end
end
end
def
map_blob_types
(
response
)
types
=
{}
response
.
each
do
|
msg
|
types
[
msg
.
path
.
dup
.
force_encoding
(
'utf-8'
)]
=
msg
.
type
.
downcase
end
types
end
end
end
end
spec/features/boards/boards_spec.rb
View file @
9c8edcd6
...
...
@@ -234,6 +234,12 @@ describe 'Issue Boards', :js do
expect
(
find
(
'.board:nth-child(2)'
)).
to
have_content
(
development
.
title
)
expect
(
find
(
'.board:nth-child(2)'
)).
to
have_content
(
planning
.
title
)
# Make sure list positions are preserved after a reload
visit
project_board_path
(
project
,
board
)
expect
(
find
(
'.board:nth-child(2)'
)).
to
have_content
(
development
.
title
)
expect
(
find
(
'.board:nth-child(2)'
)).
to
have_content
(
planning
.
title
)
end
it
'dragging does not duplicate list'
do
...
...
spec/javascripts/line_highlighter_spec.js
View file @
9c8edcd6
/* eslint-disable no-var,
prefer-template,
no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
/* eslint-disable no-var, no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
import
$
from
'
jquery
'
;
import
LineHighlighter
from
'
~/line_highlighter
'
;
...
...
@@ -8,10 +8,10 @@ describe('LineHighlighter', function() {
preloadFixtures
(
'
static/line_highlighter.html
'
);
clickLine
=
function
(
number
,
eventData
=
{})
{
if
(
$
.
isEmptyObject
(
eventData
))
{
return
$
(
'
#L
'
+
number
).
click
();
return
$
(
`#L
${
number
}
`
).
click
();
}
else
{
const
e
=
$
.
Event
(
'
click
'
,
eventData
);
return
$
(
'
#L
'
+
number
).
trigger
(
e
);
return
$
(
`#L
${
number
}
`
).
trigger
(
e
);
}
};
beforeEach
(
function
()
{
...
...
@@ -42,9 +42,9 @@ describe('LineHighlighter', function() {
var
line
;
new
LineHighlighter
({
hash
:
'
#L5-25
'
});
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
21
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
21
);
for
(
line
=
5
;
line
<=
25
;
line
+=
1
)
{
expect
(
$
(
'
#LC
'
+
line
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
`#LC
${
line
}
`
)).
toHaveClass
(
this
.
css
);
}
});
...
...
@@ -130,7 +130,7 @@ describe('LineHighlighter', function() {
});
expect
(
$
(
'
#LC13
'
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
1
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
1
);
});
it
(
'
sets the hash
'
,
function
()
{
...
...
@@ -152,9 +152,9 @@ describe('LineHighlighter', function() {
shiftKey
:
true
,
});
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
6
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
6
);
for
(
line
=
15
;
line
<=
20
;
line
+=
1
)
{
expect
(
$
(
'
#LC
'
+
line
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
`#LC
${
line
}
`
)).
toHaveClass
(
this
.
css
);
}
});
...
...
@@ -165,9 +165,9 @@ describe('LineHighlighter', function() {
shiftKey
:
true
,
});
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
6
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
6
);
for
(
line
=
5
;
line
<=
10
;
line
+=
1
)
{
expect
(
$
(
'
#LC
'
+
line
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
`#LC
${
line
}
`
)).
toHaveClass
(
this
.
css
);
}
});
});
...
...
@@ -188,9 +188,9 @@ describe('LineHighlighter', function() {
shiftKey
:
true
,
});
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
6
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
6
);
for
(
line
=
5
;
line
<=
10
;
line
+=
1
)
{
expect
(
$
(
'
#LC
'
+
line
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
`#LC
${
line
}
`
)).
toHaveClass
(
this
.
css
);
}
});
...
...
@@ -200,9 +200,9 @@ describe('LineHighlighter', function() {
shiftKey
:
true
,
});
expect
(
$
(
'
.
'
+
this
.
css
).
length
).
toBe
(
6
);
expect
(
$
(
`.
${
this
.
css
}
`
).
length
).
toBe
(
6
);
for
(
line
=
10
;
line
<=
15
;
line
+=
1
)
{
expect
(
$
(
'
#LC
'
+
line
)).
toHaveClass
(
this
.
css
);
expect
(
$
(
`#LC
${
line
}
`
)).
toHaveClass
(
this
.
css
);
}
});
});
...
...
spec/lib/banzai/filter/relative_link_filter_spec.rb
View file @
9c8edcd6
...
...
@@ -3,6 +3,9 @@
require
'spec_helper'
describe
Banzai
::
Filter
::
RelativeLinkFilter
do
include
GitHelpers
include
RepoHelpers
def
filter
(
doc
,
contexts
=
{})
contexts
.
reverse_merge!
({
commit:
commit
,
...
...
@@ -34,6 +37,12 @@ describe Banzai::Filter::RelativeLinkFilter do
%(<div>#{element}</div>)
end
def
allow_gitaly_n_plus_1
Gitlab
::
GitalyClient
.
allow_n_plus_1_calls
do
yield
end
end
let
(
:project
)
{
create
(
:project
,
:repository
,
:public
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
nil
}
...
...
@@ -44,6 +53,19 @@ describe Banzai::Filter::RelativeLinkFilter do
let
(
:requested_path
)
{
'/'
}
let
(
:only_path
)
{
true
}
it
'does not trigger a gitaly n+1'
,
:request_store
do
raw_doc
=
""
allow_gitaly_n_plus_1
do
30
.
times
do
|
i
|
create_file_in_repo
(
project
,
ref
,
ref
,
"new_file_
#{
i
}
"
,
"x"
)
raw_doc
+=
link
(
"new_file_
#{
i
}
"
)
end
end
expect
{
filter
(
raw_doc
)
}.
to
change
{
Gitlab
::
GitalyClient
.
get_request_count
}.
by
(
2
)
end
shared_examples
:preserve_unchanged
do
it
'does not modify any relative URL in anchor'
do
doc
=
filter
(
link
(
'README.md'
))
...
...
@@ -244,7 +266,8 @@ describe Banzai::Filter::RelativeLinkFilter do
end
context
'when ref name contains special chars'
do
let
(
:ref
)
{
'mark#\'@],+;-._/#@!$&()+down'
}
let
(
:ref
)
{
'mark#\'@],+;-._/#@!$&()+down'
}
let
(
:path
)
{
'files/images/logo-black.png'
}
it
'correctly escapes the ref'
do
# Addressable won't escape the '#', so we do this manually
...
...
@@ -252,8 +275,9 @@ describe Banzai::Filter::RelativeLinkFilter do
# Stub this method so the branch doesn't actually need to be in the repo
allow_any_instance_of
(
described_class
).
to
receive
(
:uri_type
).
and_return
(
:raw
)
allow_any_instance_of
(
described_class
).
to
receive
(
:get_uri_types
).
and_return
({
path: :tree
})
doc
=
filter
(
link
(
'files/images/logo-black.png'
))
doc
=
filter
(
link
(
path
))
expect
(
doc
.
at_css
(
'a'
)[
'href'
])
.
to
eq
"/
#{
project_path
}
/raw/
#{
ref_escaped
}
/files/images/logo-black.png"
...
...
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