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
7ecc247a
Commit
7ecc247a
authored
Apr 13, 2021
by
Brett Walker
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adjust class names to new references dir
for reference filters
parent
dceae94f
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
1634 additions
and
1586 deletions
+1634
-1586
ee/lib/ee/banzai/filter/references/abstract_reference_filter.rb
.../ee/banzai/filter/references/abstract_reference_filter.rb
+7
-5
ee/lib/ee/banzai/filter/references/epic_reference_filter.rb
ee/lib/ee/banzai/filter/references/epic_reference_filter.rb
+38
-36
ee/lib/ee/banzai/filter/references/iteration_reference_filter.rb
...ee/banzai/filter/references/iteration_reference_filter.rb
+82
-80
ee/lib/ee/banzai/filter/references/label_reference_filter.rb
ee/lib/ee/banzai/filter/references/label_reference_filter.rb
+16
-14
ee/lib/ee/banzai/filter/references/vulnerability_reference_filter.rb
...anzai/filter/references/vulnerability_reference_filter.rb
+44
-42
ee/lib/ee/banzai/pipeline/gfm_pipeline.rb
ee/lib/ee/banzai/pipeline/gfm_pipeline.rb
+3
-3
ee/lib/ee/banzai/pipeline/single_line_pipeline.rb
ee/lib/ee/banzai/pipeline/single_line_pipeline.rb
+3
-3
ee/spec/lib/banzai/filter/references/epic_reference_filter_spec.rb
...ib/banzai/filter/references/epic_reference_filter_spec.rb
+1
-1
ee/spec/lib/banzai/filter/references/iteration_reference_filter_spec.rb
...nzai/filter/references/iteration_reference_filter_spec.rb
+1
-1
ee/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
...b/banzai/filter/references/label_reference_filter_spec.rb
+1
-1
ee/spec/lib/banzai/filter/references/vulnerability_reference_filters_spec.rb
...filter/references/vulnerability_reference_filters_spec.rb
+1
-1
lib/banzai/filter/references/abstract_reference_filter.rb
lib/banzai/filter/references/abstract_reference_filter.rb
+335
-333
lib/banzai/filter/references/alert_reference_filter.rb
lib/banzai/filter/references/alert_reference_filter.rb
+19
-17
lib/banzai/filter/references/commit_range_reference_filter.rb
...banzai/filter/references/commit_range_reference_filter.rb
+31
-29
lib/banzai/filter/references/commit_reference_filter.rb
lib/banzai/filter/references/commit_reference_filter.rb
+61
-59
lib/banzai/filter/references/design_reference_filter.rb
lib/banzai/filter/references/design_reference_filter.rb
+81
-79
lib/banzai/filter/references/epic_reference_filter.rb
lib/banzai/filter/references/epic_reference_filter.rb
+12
-10
lib/banzai/filter/references/external_issue_reference_filter.rb
...nzai/filter/references/external_issue_reference_filter.rb
+91
-89
lib/banzai/filter/references/feature_flag_reference_filter.rb
...banzai/filter/references/feature_flag_reference_filter.rb
+22
-20
lib/banzai/filter/references/issuable_reference_filter.rb
lib/banzai/filter/references/issuable_reference_filter.rb
+11
-9
lib/banzai/filter/references/issue_reference_filter.rb
lib/banzai/filter/references/issue_reference_filter.rb
+41
-39
lib/banzai/filter/references/iteration_reference_filter.rb
lib/banzai/filter/references/iteration_reference_filter.rb
+8
-6
lib/banzai/filter/references/label_reference_filter.rb
lib/banzai/filter/references/label_reference_filter.rb
+98
-96
lib/banzai/filter/references/merge_request_reference_filter.rb
...anzai/filter/references/merge_request_reference_filter.rb
+70
-68
lib/banzai/filter/references/milestone_reference_filter.rb
lib/banzai/filter/references/milestone_reference_filter.rb
+97
-95
lib/banzai/filter/references/project_reference_filter.rb
lib/banzai/filter/references/project_reference_filter.rb
+88
-86
lib/banzai/filter/references/reference_filter.rb
lib/banzai/filter/references/reference_filter.rb
+167
-165
lib/banzai/filter/references/snippet_reference_filter.rb
lib/banzai/filter/references/snippet_reference_filter.rb
+19
-17
lib/banzai/filter/references/user_reference_filter.rb
lib/banzai/filter/references/user_reference_filter.rb
+135
-133
lib/banzai/filter/references/vulnerability_reference_filter.rb
...anzai/filter/references/vulnerability_reference_filter.rb
+12
-10
lib/banzai/pipeline/gfm_pipeline.rb
lib/banzai/pipeline/gfm_pipeline.rb
+13
-13
lib/banzai/pipeline/label_pipeline.rb
lib/banzai/pipeline/label_pipeline.rb
+1
-1
lib/banzai/pipeline/single_line_pipeline.rb
lib/banzai/pipeline/single_line_pipeline.rb
+9
-9
spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb
...anzai/filter/references/abstract_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/alert_reference_filter_spec.rb
...b/banzai/filter/references/alert_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb
...i/filter/references/commit_range_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/commit_reference_filter_spec.rb
.../banzai/filter/references/commit_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/design_reference_filter_spec.rb
.../banzai/filter/references/design_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb
...filter/references/external_issue_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb
...i/filter/references/feature_flag_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
...b/banzai/filter/references/issue_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/label_reference_filter_spec.rb
...b/banzai/filter/references/label_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
.../filter/references/merge_request_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb
...nzai/filter/references/milestone_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/project_reference_filter_spec.rb
...banzai/filter/references/project_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/reference_filter_spec.rb
spec/lib/banzai/filter/references/reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
...banzai/filter/references/snippet_reference_filter_spec.rb
+1
-1
spec/lib/banzai/filter/references/user_reference_filter_spec.rb
...ib/banzai/filter/references/user_reference_filter_spec.rb
+1
-1
spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+1
-1
No files found.
ee/lib/ee/banzai/filter/references/abstract_reference_filter.rb
View file @
7ecc247a
...
@@ -3,12 +3,14 @@
...
@@ -3,12 +3,14 @@
module
EE
module
EE
module
Banzai
module
Banzai
module
Filter
module
Filter
module
AbstractReferenceFilter
module
References
extend
::
Gitlab
::
Utils
::
Override
module
AbstractReferenceFilter
extend
::
Gitlab
::
Utils
::
Override
override
:current_project_namespace_path
override
:current_project_namespace_path
def
current_project_namespace_path
def
current_project_namespace_path
@current_project_namespace_path
||=
(
project
&
.
namespace
||
group
)
&
.
full_path
@current_project_namespace_path
||=
(
project
&
.
namespace
||
group
)
&
.
full_path
end
end
end
end
end
end
end
...
...
ee/lib/ee/banzai/filter/references/epic_reference_filter.rb
View file @
7ecc247a
...
@@ -3,51 +3,53 @@
...
@@ -3,51 +3,53 @@
module
EE
module
EE
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces epic references with links. References to
module
References
# epics that do not exist are ignored.
# HTML filter that replaces epic references with links. References to
#
# epics that do not exist are ignored.
# This filter supports cross-project/group references.
#
module
EpicReferenceFilter
# This filter supports cross-project/group references.
extend
ActiveSupport
::
Concern
module
EpicReferenceFilter
extend
ActiveSupport
::
Concern
class_methods
do
class_methods
do
def
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
def
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
text
.
gsub
(
pattern
)
do
|
match
|
symbol
=
$~
[
object_sym
]
symbol
=
$~
[
object_sym
]
if
object_class
.
reference_valid?
(
symbol
)
if
object_class
.
reference_valid?
(
symbol
)
yield
match
,
symbol
.
to_i
,
nil
,
$~
[
:group
],
$~
yield
match
,
symbol
.
to_i
,
nil
,
$~
[
:group
],
$~
else
else
match
match
end
end
end
end
end
end
end
end
def
url_for_object
(
epic
,
group
)
def
url_for_object
(
epic
,
group
)
urls
=
::
Gitlab
::
Routing
.
url_helpers
urls
=
::
Gitlab
::
Routing
.
url_helpers
urls
.
group_epic_url
(
group
,
epic
,
only_path:
context
[
:only_path
])
urls
.
group_epic_url
(
group
,
epic
,
only_path:
context
[
:only_path
])
end
end
def
data_attributes_for
(
text
,
group
,
object
,
link_content:
false
,
link_reference:
false
)
def
data_attributes_for
(
text
,
group
,
object
,
link_content:
false
,
link_reference:
false
)
{
{
original:
escape_html_entities
(
text
),
original:
escape_html_entities
(
text
),
link:
link_content
,
link:
link_content
,
link_reference:
link_reference
,
link_reference:
link_reference
,
group:
group
.
id
,
group:
group
.
id
,
object_sym
=>
object
.
id
object_sym
=>
object
.
id
}
}
end
end
# rubocop: disable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
epics
.
where
(
iid:
ids
.
to_a
)
parent
.
epics
.
where
(
iid:
ids
.
to_a
)
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: enable CodeReuse/ActiveRecord
private
private
def
parent_type
def
parent_type
:group
:group
end
end
end
end
end
end
end
...
...
ee/lib/ee/banzai/filter/references/iteration_reference_filter.rb
View file @
7ecc247a
...
@@ -3,113 +3,115 @@
...
@@ -3,113 +3,115 @@
module
EE
module
EE
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces iteration references with links.
module
References
module
IterationReferenceFilter
# HTML filter that replaces iteration references with links.
include
::
Gitlab
::
Utils
::
StrongMemoize
module
IterationReferenceFilter
include
::
Gitlab
::
Utils
::
StrongMemoize
def
find_object
(
parent
,
id
)
def
find_object
(
parent
,
id
)
return
unless
valid_context?
(
parent
)
return
unless
valid_context?
(
parent
)
find_iteration
(
parent
,
id:
id
)
find_iteration
(
parent
,
id:
id
)
end
def
valid_context?
(
parent
)
group_context?
(
parent
)
||
project_context?
(
parent
)
end
def
group_context?
(
parent
)
strong_memoize
(
:group_context
)
do
parent
.
is_a?
(
Group
)
end
end
end
def
project_context?
(
parent
)
def
valid_context?
(
parent
)
strong_memoize
(
:project_context
)
do
group_context?
(
parent
)
||
project_context?
(
parent
)
parent
.
is_a?
(
Project
)
end
end
end
def
references_in
(
text
,
pattern
=
::
Iteration
.
reference_pattern
)
def
group_context?
(
parent
)
# We'll handle here the references that follow the `reference_pattern`.
strong_memoize
(
:group_context
)
do
# Other patterns (for example, the link pattern) are handled by the
parent
.
is_a?
(
Group
)
# default implementation.
end
return
super
(
text
,
pattern
)
if
pattern
!=
::
Iteration
.
reference_pattern
end
iterations
=
{}
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
iteration
=
parse_and_find_iteration
(
$~
[
:project
],
$~
[
:namespace
],
$~
[
:iteration_id
],
$~
[
:iteration_name
])
if
iteration
def
project_context?
(
parent
)
iterations
[
iteration
.
id
]
=
yield
match
,
iteration
.
id
,
$~
[
:project
],
$~
[
:namespace
],
$~
strong_memoize
(
:project_context
)
do
"
#{
::
Banzai
::
Filter
::
AbstractReferenceFilter
::
REFERENCE_PLACEHOLDER
}#{
iteration
.
id
}
"
parent
.
is_a?
(
Project
)
else
match
end
end
end
end
return
text
if
iterations
.
empty?
def
references_in
(
text
,
pattern
=
::
Iteration
.
reference_pattern
)
# We'll handle here the references that follow the `reference_pattern`.
# Other patterns (for example, the link pattern) are handled by the
# default implementation.
return
super
(
text
,
pattern
)
if
pattern
!=
::
Iteration
.
reference_pattern
iterations
=
{}
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
iteration
=
parse_and_find_iteration
(
$~
[
:project
],
$~
[
:namespace
],
$~
[
:iteration_id
],
$~
[
:iteration_name
])
if
iteration
iterations
[
iteration
.
id
]
=
yield
match
,
iteration
.
id
,
$~
[
:project
],
$~
[
:namespace
],
$~
"
#{
::
Banzai
::
Filter
::
References
::
AbstractReferenceFilter
::
REFERENCE_PLACEHOLDER
}#{
iteration
.
id
}
"
else
match
end
end
escape_with_placeholders
(
unescaped_html
,
iterations
)
return
text
if
iterations
.
empty?
end
def
parse_and_find_iteration
(
project_ref
,
namespace_ref
,
iteration_id
,
iteration_name
)
escape_with_placeholders
(
unescaped_html
,
iterations
)
project_path
=
full_project_path
(
namespace_ref
,
project_ref
)
end
# Returns group if project is not found by path
def
parse_and_find_iteration
(
project_ref
,
namespace_ref
,
iteration_id
,
iteration_name
)
parent
=
parent_from_ref
(
project_path
)
project_path
=
full_project_path
(
namespace_ref
,
project_ref
)
return
unless
parent
# Returns group if project is not found by path
parent
=
parent_from_ref
(
project_path
)
iteration_params
=
iteration_params
(
iteration_id
,
iteration_name
)
return
unless
parent
find_iteration
(
parent
,
iteration_params
)
iteration_params
=
iteration_params
(
iteration_id
,
iteration_name
)
end
def
iteration_params
(
id
,
name
)
find_iteration
(
parent
,
iteration_params
)
if
name
{
name:
name
.
tr
(
'"'
,
''
)
}
else
{
id:
id
.
to_i
}
end
end
end
# rubocop: disable CodeReuse/ActiveRecord
def
iteration_params
(
id
,
name
)
def
find_iteration
(
parent
,
params
)
if
name
::
Iteration
.
for_projects_and_groups
(
project_ids
(
parent
),
group_and_ancestors_ids
(
parent
)).
find_by
(
**
params
)
{
name:
name
.
tr
(
'"'
,
''
)
}
end
else
# rubocop: enable CodeReuse/ActiveRecord
{
id:
id
.
to_i
}
end
end
def
project_ids
(
parent
)
# rubocop: disable CodeReuse/ActiveRecord
parent
.
id
if
project_context?
(
parent
)
def
find_iteration
(
parent
,
params
)
end
::
Iteration
.
for_projects_and_groups
(
project_ids
(
parent
),
group_and_ancestors_ids
(
parent
)).
find_by
(
**
params
)
end
# rubocop: enable CodeReuse/ActiveRecord
def
group_and_ancestors_ids
(
parent
)
def
project_ids
(
parent
)
if
group_context?
(
parent
)
parent
.
id
if
project_context?
(
parent
)
parent
.
self_and_ancestors
.
select
(
:id
)
elsif
project_context?
(
parent
)
parent
.
group
&
.
self_and_ancestors
&
.
select
(
:id
)
end
end
end
def
url_for_object
(
iteration
,
_parent
)
def
group_and_ancestors_ids
(
parent
)
::
Gitlab
::
Routing
if
group_context?
(
parent
)
.
url_helpers
parent
.
self_and_ancestors
.
select
(
:id
)
.
iteration_url
(
iteration
,
only_path:
context
[
:only_path
])
elsif
project_context?
(
parent
)
end
parent
.
group
&
.
self_and_ancestors
&
.
select
(
:id
)
end
end
def
url_for_object
(
iteration
,
_parent
)
::
Gitlab
::
Routing
.
url_helpers
.
iteration_url
(
iteration
,
only_path:
context
[
:only_path
])
end
def
object_link_text
(
object
,
matches
)
def
object_link_text
(
object
,
matches
)
iteration_link
=
escape_once
(
super
)
iteration_link
=
escape_once
(
super
)
reference
=
object
.
project
&
.
to_reference_base
(
project
)
reference
=
object
.
project
&
.
to_reference_base
(
project
)
if
reference
.
present?
if
reference
.
present?
"
#{
iteration_link
}
<i>in
#{
reference
}
</i>"
.
html_safe
"
#{
iteration_link
}
<i>in
#{
reference
}
</i>"
.
html_safe
else
else
iteration_link
iteration_link
end
end
end
end
def
object_link_title
(
_object
,
_matches
)
def
object_link_title
(
_object
,
_matches
)
'Iteration'
'Iteration'
end
end
end
end
end
end
end
...
...
ee/lib/ee/banzai/filter/references/label_reference_filter.rb
View file @
7ecc247a
...
@@ -3,24 +3,26 @@
...
@@ -3,24 +3,26 @@
module
EE
module
EE
module
Banzai
module
Banzai
module
Filter
module
Filter
module
LabelReferenceFilter
module
References
extend
::
Gitlab
::
Utils
::
Override
module
LabelReferenceFilter
extend
::
Gitlab
::
Utils
::
Override
override
:data_attributes_for
override
:data_attributes_for
def
data_attributes_for
(
text
,
parent
,
object
,
link_content:
false
,
link_reference:
false
)
def
data_attributes_for
(
text
,
parent
,
object
,
link_content:
false
,
link_reference:
false
)
return
super
unless
object
.
scoped_label?
return
super
unless
object
.
scoped_label?
# Enabling HTML tooltips for scoped labels here and additional escaping is done in `object_link_title`
# Enabling HTML tooltips for scoped labels here and additional escaping is done in `object_link_title`
super
.
merge!
(
super
.
merge!
(
html:
true
html:
true
)
)
end
end
override
:object_link_title
override
:object_link_title
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
return
super
unless
object
.
scoped_label?
return
super
unless
object
.
scoped_label?
ERB
::
Util
.
html_escape
(
super
)
ERB
::
Util
.
html_escape
(
super
)
end
end
end
end
end
end
end
...
...
ee/lib/ee/banzai/filter/references/vulnerability_reference_filter.rb
View file @
7ecc247a
...
@@ -3,61 +3,63 @@
...
@@ -3,61 +3,63 @@
module
EE
module
EE
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces vulnerability references with links. References to
module
References
# vulnerabilities that do not exist are ignored.
# HTML filter that replaces vulnerability references with links. References to
#
# vulnerabilities that do not exist are ignored.
# This filter supports cross-project/group references.
#
module
VulnerabilityReferenceFilter
# This filter supports cross-project/group references.
extend
ActiveSupport
::
Concern
module
VulnerabilityReferenceFilter
extend
ActiveSupport
::
Concern
class_methods
do
class_methods
do
def
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
def
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
text
.
gsub
(
pattern
)
do
|
match
|
symbol
=
$~
[
object_sym
]
symbol
=
$~
[
object_sym
]
if
object_class
.
reference_valid?
(
symbol
)
if
object_class
.
reference_valid?
(
symbol
)
yield
match
,
symbol
.
to_i
,
$~
[
:project
],
$~
[
:namespace
],
$~
yield
match
,
symbol
.
to_i
,
$~
[
:project
],
$~
[
:namespace
],
$~
else
else
match
match
end
end
end
end
end
end
end
end
def
unescape_link
(
href
)
def
unescape_link
(
href
)
return
href
if
href
=~
object_class
.
reference_pattern
return
href
if
href
=~
object_class
.
reference_pattern
super
super
end
end
def
url_for_object
(
vulnerability
,
project
)
def
url_for_object
(
vulnerability
,
project
)
urls
=
::
Gitlab
::
Routing
.
url_helpers
urls
=
::
Gitlab
::
Routing
.
url_helpers
urls
.
project_security_vulnerability_url
(
project
,
vulnerability
,
only_path:
context
[
:only_path
])
urls
.
project_security_vulnerability_url
(
project
,
vulnerability
,
only_path:
context
[
:only_path
])
end
end
def
data_attributes_for
(
text
,
project
,
object
,
link_content:
false
,
link_reference:
false
)
def
data_attributes_for
(
text
,
project
,
object
,
link_content:
false
,
link_reference:
false
)
{
{
original:
escape_html_entities
(
text
),
original:
escape_html_entities
(
text
),
link:
link_content
,
link:
link_content
,
link_reference:
link_reference
,
link_reference:
link_reference
,
project:
project
.
id
,
project:
project
.
id
,
object_sym
=>
object
.
id
object_sym
=>
object
.
id
}
}
end
end
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
return
::
Vulnerability
.
none
if
ids
.
blank?
||
parent
.
nil?
return
::
Vulnerability
.
none
if
ids
.
blank?
||
parent
.
nil?
parent
.
vulnerabilities
.
id_in
(
ids
.
to_a
)
parent
.
vulnerabilities
.
id_in
(
ids
.
to_a
)
end
end
def
record_identifier
(
record
)
def
record_identifier
(
record
)
record
.
id
.
to_i
record
.
id
.
to_i
end
end
private
private
def
parent_type
def
parent_type
:project
:project
end
end
end
end
end
end
end
...
...
ee/lib/ee/banzai/pipeline/gfm_pipeline.rb
View file @
7ecc247a
...
@@ -16,9 +16,9 @@ module EE
...
@@ -16,9 +16,9 @@ module EE
def
reference_filters
def
reference_filters
[
[
::
Banzai
::
Filter
::
EpicReferenceFilter
,
::
Banzai
::
Filter
::
References
::
EpicReferenceFilter
,
::
Banzai
::
Filter
::
IterationReferenceFilter
,
::
Banzai
::
Filter
::
References
::
IterationReferenceFilter
,
::
Banzai
::
Filter
::
VulnerabilityReferenceFilter
,
::
Banzai
::
Filter
::
References
::
VulnerabilityReferenceFilter
,
*
super
*
super
]
]
end
end
...
...
ee/lib/ee/banzai/pipeline/single_line_pipeline.rb
View file @
7ecc247a
...
@@ -9,9 +9,9 @@ module EE
...
@@ -9,9 +9,9 @@ module EE
class_methods
do
class_methods
do
def
reference_filters
def
reference_filters
[
[
::
Banzai
::
Filter
::
EpicReferenceFilter
,
::
Banzai
::
Filter
::
References
::
EpicReferenceFilter
,
::
Banzai
::
Filter
::
IterationReferenceFilter
,
::
Banzai
::
Filter
::
References
::
IterationReferenceFilter
,
::
Banzai
::
Filter
::
VulnerabilityReferenceFilter
,
::
Banzai
::
Filter
::
References
::
VulnerabilityReferenceFilter
,
*
super
*
super
]
]
end
end
...
...
ee/spec/lib/banzai/filter/references/epic_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
EpicReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
EpicReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:urls
)
{
Gitlab
::
Routing
.
url_helpers
}
let
(
:urls
)
{
Gitlab
::
Routing
.
url_helpers
}
...
...
ee/spec/lib/banzai/filter/references/iteration_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
IterationReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
IterationReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:parent_group
)
{
create
(
:group
,
:public
)
}
let
(
:parent_group
)
{
create
(
:group
,
:public
)
}
...
...
ee/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
LabelReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
LabelReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
,
name:
'sample-project'
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
name:
'sample-project'
)
}
...
...
ee/spec/lib/banzai/filter/references/vulnerability_reference_filters_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
VulnerabilityReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
VulnerabilityReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:urls
)
{
Gitlab
::
Routing
.
url_helpers
}
let
(
:urls
)
{
Gitlab
::
Routing
.
url_helpers
}
...
...
lib/banzai/filter/references/abstract_reference_filter.rb
View file @
7ecc247a
...
@@ -2,445 +2,447 @@
...
@@ -2,445 +2,447 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# Issues, merge requests, Snippets, Commits and Commit Ranges share
module
References
# similar functionality in reference filtering.
# Issues, merge requests, Snippets, Commits and Commit Ranges share
class
AbstractReferenceFilter
<
ReferenceFilter
# similar functionality in reference filtering.
include
CrossProjectReference
class
AbstractReferenceFilter
<
ReferenceFilter
include
CrossProjectReference
# REFERENCE_PLACEHOLDER is used for re-escaping HTML text except found
# reference (which we replace with placeholder during re-scaping). The
# REFERENCE_PLACEHOLDER is used for re-escaping HTML text except found
# random number helps ensure it's pretty close to unique. Since it's a
# reference (which we replace with placeholder during re-scaping). The
# transitory value (it never gets saved) we can initialize once, and it
# random number helps ensure it's pretty close to unique. Since it's a
# doesn't matter if it changes on a restart.
# transitory value (it never gets saved) we can initialize once, and it
REFERENCE_PLACEHOLDER
=
"_reference_
#{
SecureRandom
.
hex
(
16
)
}
_"
# doesn't matter if it changes on a restart.
REFERENCE_PLACEHOLDER_PATTERN
=
%r{
#{
REFERENCE_PLACEHOLDER
}
(
\d
+)}
.
freeze
REFERENCE_PLACEHOLDER
=
"_reference_
#{
SecureRandom
.
hex
(
16
)
}
_"
REFERENCE_PLACEHOLDER_PATTERN
=
%r{
#{
REFERENCE_PLACEHOLDER
}
(
\d
+)}
.
freeze
def
self
.
object_class
# Implement in child class
def
self
.
object_class
# Example: MergeRequest
# Implement in child class
end
# Example: MergeRequest
end
def
self
.
object_name
def
self
.
object_name
@object_name
||=
object_class
.
name
.
underscore
@object_name
||=
object_class
.
name
.
underscore
end
end
def
self
.
object_sym
def
self
.
object_sym
@object_sym
||=
object_name
.
to_sym
@object_sym
||=
object_name
.
to_sym
end
end
# Public: Find references in text (like `!123` for merge requests)
# Public: Find references in text (like `!123` for merge requests)
#
#
# AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches|
# AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches|
# object = find_object(project_ref, id)
# object = find_object(project_ref, id)
# "<a href=...>#{object.to_reference}</a>"
# "<a href=...>#{object.to_reference}</a>"
# end
# end
#
#
# text - String text to search.
# text - String text to search.
#
#
# Yields the String match, the Integer referenced object ID, an optional String
# Yields the String match, the Integer referenced object ID, an optional String
# of the external project reference, and all of the matchdata.
# of the external project reference, and all of the matchdata.
#
#
# Returns a String replaced with the return of the block.
# Returns a String replaced with the return of the block.
def
self
.
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
def
self
.
references_in
(
text
,
pattern
=
object_class
.
reference_pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
text
.
gsub
(
pattern
)
do
|
match
|
if
ident
=
identifier
(
$~
)
if
ident
=
identifier
(
$~
)
yield
match
,
ident
,
$~
[
:project
],
$~
[
:namespace
],
$~
yield
match
,
ident
,
$~
[
:project
],
$~
[
:namespace
],
$~
else
else
match
match
end
end
end
end
end
end
def
self
.
identifier
(
match_data
)
def
self
.
identifier
(
match_data
)
symbol
=
symbol_from_match
(
match_data
)
symbol
=
symbol_from_match
(
match_data
)
parse_symbol
(
symbol
,
match_data
)
if
object_class
.
reference_valid?
(
symbol
)
end
def
identifier
(
match_data
)
parse_symbol
(
symbol
,
match_data
)
if
object_class
.
reference_valid?
(
symbol
)
self
.
class
.
identifier
(
match_data
)
end
end
def
self
.
symbol_from_match
(
match
)
key
=
object_sym
match
[
key
]
if
match
.
names
.
include?
(
key
.
to_s
)
end
# Transform a symbol extracted from the text to a meaningful value
def
identifier
(
match_data
)
# In most cases these will be integers, so we call #to_i by default
self
.
class
.
identifier
(
match_data
)
#
end
# This method has the contract that if a string `ref` refers to a
# record `record`, then `parse_symbol(ref) == record_identifier(record)`.
def
self
.
parse_symbol
(
symbol
,
match_data
)
symbol
.
to_i
end
# We assume that most classes are identifying records by ID.
def
self
.
symbol_from_match
(
match
)
#
key
=
object_sym
# This method has the contract that if a string `ref` refers to a
match
[
key
]
if
match
.
names
.
include?
(
key
.
to_s
)
# record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
end
def
record_identifier
(
record
)
record
.
id
end
def
object_class
# Transform a symbol extracted from the text to a meaningful value
self
.
class
.
object_class
# In most cases these will be integers, so we call #to_i by default
end
#
# This method has the contract that if a string `ref` refers to a
# record `record`, then `parse_symbol(ref) == record_identifier(record)`.
def
self
.
parse_symbol
(
symbol
,
match_data
)
symbol
.
to_i
end
def
object_sym
# We assume that most classes are identifying records by ID.
self
.
class
.
object_sym
#
end
# This method has the contract that if a string `ref` refers to a
# record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
def
record_identifier
(
record
)
record
.
id
end
def
references_in
(
*
args
,
&
block
)
def
object_class
self
.
class
.
references_in
(
*
args
,
&
block
)
self
.
class
.
object_class
end
end
# Implement in child class
def
object_sym
# Example: project.merge_requests.find
self
.
class
.
object_sym
def
find_object
(
parent_object
,
id
)
end
end
# Override if the link reference pattern produces a different ID (global
def
references_in
(
*
args
,
&
block
)
# ID vs internal ID, for instance) to the regular reference pattern.
self
.
class
.
references_in
(
*
args
,
&
block
)
def
find_object_from_link
(
parent_object
,
id
)
end
find_object
(
parent_object
,
id
)
end
# Implement in child class
# Implement in child class
# Example: project_merge_request_url
# Example: project.merge_requests.find
def
url_for_object
(
object
,
parent_object
)
def
find_object
(
parent_object
,
id
)
end
end
def
find_object_cached
(
parent_object
,
id
)
# Override if the link reference pattern produces a different ID (global
cached_call
(
:banzai_find_object
,
id
,
path:
[
object_class
,
parent_object
.
id
])
do
# ID vs internal ID, for instance) to the regular reference pattern.
def
find_object_from_link
(
parent_object
,
id
)
find_object
(
parent_object
,
id
)
find_object
(
parent_object
,
id
)
end
end
end
def
find_object_from_link_cached
(
parent_object
,
id
)
# Implement in child class
cached_call
(
:banzai_find_object_from_link
,
id
,
path:
[
object_class
,
parent_object
.
id
])
do
# Example: project_merge_request_url
find_object_from_link
(
parent_object
,
id
)
def
url_for_object
(
object
,
parent_object
)
end
end
end
def
from_ref_cached
(
ref
)
def
find_object_cached
(
parent_object
,
id
)
cached_call
(
"banzai_
#{
parent_type
}
_refs"
.
to_sym
,
ref
)
do
cached_call
(
:banzai_find_object
,
id
,
path:
[
object_class
,
parent_object
.
id
])
do
parent_from_ref
(
ref
)
find_object
(
parent_object
,
id
)
end
end
end
end
def
url_for_object_cached
(
object
,
parent_object
)
def
find_object_from_link_cached
(
parent_object
,
id
)
cached_call
(
:banzai_url_for_object
,
object
,
path:
[
object_class
,
parent_object
.
id
])
do
cached_call
(
:banzai_find_object_from_link
,
id
,
path:
[
object_class
,
parent_object
.
id
])
do
url_for_object
(
object
,
parent_object
)
find_object_from_link
(
parent_object
,
id
)
end
end
end
end
def
call
def
from_ref_cached
(
ref
)
return
doc
unless
project
||
group
||
user
cached_call
(
"banzai_
#{
parent_type
}
_refs"
.
to_sym
,
ref
)
do
parent_from_ref
(
ref
)
end
end
ref_pattern
=
object_class
.
reference_pattern
def
url_for_object_cached
(
object
,
parent_object
)
link_pattern
=
object_class
.
link_reference_pattern
cached_call
(
:banzai_url_for_object
,
object
,
path:
[
object_class
,
parent_object
.
id
])
do
url_for_object
(
object
,
parent_object
)
end
end
# Compile often used regexps only once outside of the loop
def
call
ref_pattern_anchor
=
/\A
#{
ref_pattern
}
\z/
return
doc
unless
project
||
group
||
user
link_pattern_start
=
/\A
#{
link_pattern
}
/
link_pattern_anchor
=
/\A
#{
link_pattern
}
\z/
nodes
.
each_with_index
do
|
node
,
index
|
ref_pattern
=
object_class
.
reference_pattern
if
text_node?
(
node
)
&&
ref_pattern
link_pattern
=
object_class
.
link_reference_pattern
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
object_link_filter
(
content
,
ref_pattern
)
end
elsif
element_node?
(
node
)
# Compile often used regexps only once outside of the loop
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
ref_pattern_anchor
=
/\A
#{
ref_pattern
}
\z/
if
ref_pattern
&&
link
=~
ref_pattern_anchor
link_pattern_start
=
/\A
#{
link_pattern
}
/
replace_link_node_with_href
(
node
,
index
,
link
)
do
link_pattern_anchor
=
/\A
#{
link_pattern
}
\z/
object_link_filter
(
link
,
ref_pattern
,
link_content:
inner_html
)
end
next
nodes
.
each_with_index
do
|
node
,
index
|
if
text_node?
(
node
)
&&
ref_pattern
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
object_link_filter
(
content
,
ref_pattern
)
end
end
next
unless
link_pattern
elsif
element_node?
(
node
)
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
if
ref_pattern
&&
link
=~
ref_pattern_anchor
replace_link_node_with_href
(
node
,
index
,
link
)
do
object_link_filter
(
link
,
ref_pattern
,
link_content:
inner_html
)
end
if
link
==
inner_html
&&
inner_html
=~
link_pattern_start
next
replace_link_node_with_text
(
node
,
index
)
do
object_link_filter
(
inner_html
,
link_pattern
,
link_reference:
true
)
end
end
next
next
unless
link_pattern
end
if
link
=~
link_pattern_anchor
if
link
==
inner_html
&&
inner_html
=~
link_pattern_start
replace_link_node_with_href
(
node
,
index
,
link
)
do
replace_link_node_with_text
(
node
,
index
)
do
object_link_filter
(
link
,
link_pattern
,
link_content:
inner_html
,
link_reference:
true
)
object_link_filter
(
inner_html
,
link_pattern
,
link_reference:
true
)
end
next
end
end
next
if
link
=~
link_pattern_anchor
replace_link_node_with_href
(
node
,
index
,
link
)
do
object_link_filter
(
link
,
link_pattern
,
link_content:
inner_html
,
link_reference:
true
)
end
next
end
end
end
end
end
end
end
end
doc
doc
end
end
# Replace references (like `!123` for merge requests) in text with links
# Replace references (like `!123` for merge requests) in text with links
# to the referenced object's details page.
# to the referenced object's details page.
#
#
# text - String text to replace references in.
# text - String text to replace references in.
# pattern - Reference pattern to match against.
# pattern - Reference pattern to match against.
# link_content - Original content of the link being replaced.
# link_content - Original content of the link being replaced.
# link_reference - True if this was using the link reference pattern,
# link_reference - True if this was using the link reference pattern,
# false otherwise.
# false otherwise.
#
#
# Returns a String with references replaced with links. All links
# Returns a String with references replaced with links. All links
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
def
object_link_filter
(
text
,
pattern
,
link_content:
nil
,
link_reference:
false
)
def
object_link_filter
(
text
,
pattern
,
link_content:
nil
,
link_reference:
false
)
references_in
(
text
,
pattern
)
do
|
match
,
id
,
project_ref
,
namespace_ref
,
matches
|
references_in
(
text
,
pattern
)
do
|
match
,
id
,
project_ref
,
namespace_ref
,
matches
|
parent_path
=
if
parent_type
==
:group
parent_path
=
if
parent_type
==
:group
full_group_path
(
namespace_ref
)
full_group_path
(
namespace_ref
)
else
else
full_project_path
(
namespace_ref
,
project_ref
)
full_project_path
(
namespace_ref
,
project_ref
)
end
end
parent
=
from_ref_cached
(
parent_path
)
parent
=
from_ref_cached
(
parent_path
)
if
parent
if
parent
object
=
object
=
if
link_reference
if
link_reference
find_object_from_link_cached
(
parent
,
id
)
find_object_from_link_cached
(
parent
,
id
)
else
else
find_object_cached
(
parent
,
id
)
find_object_cached
(
parent
,
id
)
end
end
end
end
if
object
if
object
title
=
object_link_title
(
object
,
matches
)
title
=
object_link_title
(
object
,
matches
)
klass
=
reference_class
(
object_sym
)
klass
=
reference_class
(
object_sym
)
data_attributes
=
data_attributes_for
(
link_content
||
match
,
parent
,
object
,
data_attributes
=
data_attributes_for
(
link_content
||
match
,
parent
,
object
,
link_content:
!!
link_content
,
link_content:
!!
link_content
,
link_reference:
link_reference
)
link_reference:
link_reference
)
data
=
data_attribute
(
data_attributes
)
data
=
data_attribute
(
data_attributes
)
url
=
url
=
if
matches
.
names
.
include?
(
"url"
)
&&
matches
[
:url
]
if
matches
.
names
.
include?
(
"url"
)
&&
matches
[
:url
]
matches
[
:url
]
matches
[
:url
]
else
else
url_for_object_cached
(
object
,
parent
)
url_for_object_cached
(
object
,
parent
)
end
end
content
=
link_content
||
object_link_text
(
object
,
matches
)
content
=
link_content
||
object_link_text
(
object
,
matches
)
link
=
%(<a href="#{url}" #{data}
link
=
%(<a href="#{url}" #{data}
title="#{escape_once(title)}"
title="#{escape_once(title)}"
class="#{klass}">#{content}</a>)
class="#{klass}">#{content}</a>)
wrap_link
(
link
,
object
)
wrap_link
(
link
,
object
)
else
else
match
match
end
end
end
end
end
end
def
wrap_link
(
link
,
object
)
def
wrap_link
(
link
,
object
)
link
link
end
end
def
data_attributes_for
(
text
,
parent
,
object
,
link_content:
false
,
link_reference:
false
)
def
data_attributes_for
(
text
,
parent
,
object
,
link_content:
false
,
link_reference:
false
)
object_parent_type
=
parent
.
is_a?
(
Group
)
?
:group
:
:project
object_parent_type
=
parent
.
is_a?
(
Group
)
?
:group
:
:project
{
{
original:
escape_html_entities
(
text
),
original:
escape_html_entities
(
text
),
link:
link_content
,
link:
link_content
,
link_reference:
link_reference
,
link_reference:
link_reference
,
object_parent_type
=>
parent
.
id
,
object_parent_type
=>
parent
.
id
,
object_sym
=>
object
.
id
object_sym
=>
object
.
id
}
}
end
end
def
object_link_text_extras
(
object
,
matches
)
def
object_link_text_extras
(
object
,
matches
)
extras
=
[]
extras
=
[]
if
matches
.
names
.
include?
(
"anchor"
)
&&
matches
[
:anchor
]
&&
matches
[
:anchor
]
=~
/\A\#note_(\d+)\z/
if
matches
.
names
.
include?
(
"anchor"
)
&&
matches
[
:anchor
]
&&
matches
[
:anchor
]
=~
/\A\#note_(\d+)\z/
extras
<<
"comment
#{
Regexp
.
last_match
(
1
)
}
"
extras
<<
"comment
#{
Regexp
.
last_match
(
1
)
}
"
end
end
extension
=
matches
[
:extension
]
if
matches
.
names
.
include?
(
"extension"
)
extension
=
matches
[
:extension
]
if
matches
.
names
.
include?
(
"extension"
)
extras
<<
extension
if
extension
extras
<<
extension
if
extension
extras
extras
end
end
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
object
.
title
object
.
title
end
end
def
object_link_text
(
object
,
matches
)
def
object_link_text
(
object
,
matches
)
parent
=
project
||
group
||
user
parent
=
project
||
group
||
user
text
=
object
.
reference_link_text
(
parent
)
text
=
object
.
reference_link_text
(
parent
)
extras
=
object_link_text_extras
(
object
,
matches
)
extras
=
object_link_text_extras
(
object
,
matches
)
text
+=
" (
#{
extras
.
join
(
", "
)
}
)"
if
extras
.
any?
text
+=
" (
#{
extras
.
join
(
", "
)
}
)"
if
extras
.
any?
text
text
end
end
# Returns a Hash containing all object references (e.g. issue IDs) per the
# Returns a Hash containing all object references (e.g. issue IDs) per the
# project they belong to.
# project they belong to.
def
references_per_parent
def
references_per_parent
@references_per
||=
{}
@references_per
||=
{}
@references_per
[
parent_type
]
||=
begin
@references_per
[
parent_type
]
||=
begin
refs
=
Hash
.
new
{
|
hash
,
key
|
hash
[
key
]
=
Set
.
new
}
refs
=
Hash
.
new
{
|
hash
,
key
|
hash
[
key
]
=
Set
.
new
}
regex
=
[
regex
=
[
object_class
.
link_reference_pattern
,
object_class
.
link_reference_pattern
,
object_class
.
reference_pattern
object_class
.
reference_pattern
].
compact
.
reduce
{
|
a
,
b
|
Regexp
.
union
(
a
,
b
)
}
].
compact
.
reduce
{
|
a
,
b
|
Regexp
.
union
(
a
,
b
)
}
nodes
.
each
do
|
node
|
nodes
.
each
do
|
node
|
node
.
to_html
.
scan
(
regex
)
do
node
.
to_html
.
scan
(
regex
)
do
path
=
if
parent_type
==
:project
path
=
if
parent_type
==
:project
full_project_path
(
$~
[
:namespace
],
$~
[
:project
])
full_project_path
(
$~
[
:namespace
],
$~
[
:project
])
else
else
full_group_path
(
$~
[
:group
])
full_group_path
(
$~
[
:group
])
end
end
if
ident
=
identifier
(
$~
)
if
ident
=
identifier
(
$~
)
refs
[
path
]
<<
ident
refs
[
path
]
<<
ident
end
end
end
end
end
end
refs
refs
end
end
end
end
# Returns a Hash containing referenced projects grouped per their full
# Returns a Hash containing referenced projects grouped per their full
# path.
# path.
def
parent_per_reference
def
parent_per_reference
@per_reference
||=
{}
@per_reference
||=
{}
@per_reference
[
parent_type
]
||=
begin
@per_reference
[
parent_type
]
||=
begin
refs
=
Set
.
new
refs
=
Set
.
new
references_per_parent
.
each
do
|
ref
,
_
|
references_per_parent
.
each
do
|
ref
,
_
|
refs
<<
ref
refs
<<
ref
end
end
find_for_paths
(
refs
.
to_a
).
index_by
(
&
:full_path
)
find_for_paths
(
refs
.
to_a
).
index_by
(
&
:full_path
)
end
end
end
end
def
relation_for_paths
(
paths
)
def
relation_for_paths
(
paths
)
klass
=
parent_type
.
to_s
.
camelize
.
constantize
klass
=
parent_type
.
to_s
.
camelize
.
constantize
result
=
klass
.
where_full_path_in
(
paths
)
result
=
klass
.
where_full_path_in
(
paths
)
return
result
if
parent_type
==
:group
return
result
if
parent_type
==
:group
result
.
includes
(
:namespace
)
if
parent_type
==
:project
result
.
includes
(
:namespace
)
if
parent_type
==
:project
end
end
# Returns projects for the given paths.
# Returns projects for the given paths.
def
find_for_paths
(
paths
)
def
find_for_paths
(
paths
)
if
Gitlab
::
SafeRequestStore
.
active?
if
Gitlab
::
SafeRequestStore
.
active?
cache
=
refs_cache
cache
=
refs_cache
to_query
=
paths
-
cache
.
keys
to_query
=
paths
-
cache
.
keys
unless
to_query
.
empty?
unless
to_query
.
empty?
records
=
relation_for_paths
(
to_query
)
records
=
relation_for_paths
(
to_query
)
found
=
[]
found
=
[]
records
.
each
do
|
record
|
records
.
each
do
|
record
|
ref
=
record
.
full_path
ref
=
record
.
full_path
get_or_set_cache
(
cache
,
ref
)
{
record
}
get_or_set_cache
(
cache
,
ref
)
{
record
}
found
<<
ref
found
<<
ref
end
end
not_found
=
to_query
-
found
not_found
=
to_query
-
found
not_found
.
each
do
|
ref
|
not_found
.
each
do
|
ref
|
get_or_set_cache
(
cache
,
ref
)
{
nil
}
get_or_set_cache
(
cache
,
ref
)
{
nil
}
end
end
end
end
cache
.
slice
(
*
paths
).
values
.
compact
cache
.
slice
(
*
paths
).
values
.
compact
else
else
relation_for_paths
(
paths
)
relation_for_paths
(
paths
)
end
end
end
end
def
current_parent_path
def
current_parent_path
@current_parent_path
||=
parent
&
.
full_path
@current_parent_path
||=
parent
&
.
full_path
end
end
def
current_project_namespace_path
def
current_project_namespace_path
@current_project_namespace_path
||=
project
&
.
namespace
&
.
full_path
@current_project_namespace_path
||=
project
&
.
namespace
&
.
full_path
end
end
def
records_per_parent
def
records_per_parent
@_records_per_project
||=
{}
@_records_per_project
||=
{}
@_records_per_project
[
object_class
.
to_s
.
underscore
]
||=
begin
@_records_per_project
[
object_class
.
to_s
.
underscore
]
||=
begin
hash
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
{}
}
hash
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
{}
}
parent_per_reference
.
each
do
|
path
,
parent
|
parent_per_reference
.
each
do
|
path
,
parent
|
record_ids
=
references_per_parent
[
path
]
record_ids
=
references_per_parent
[
path
]
parent_records
(
parent
,
record_ids
).
each
do
|
record
|
parent_records
(
parent
,
record_ids
).
each
do
|
record
|
hash
[
parent
][
record_identifier
(
record
)]
=
record
hash
[
parent
][
record_identifier
(
record
)]
=
record
end
end
end
end
hash
hash
end
end
end
end
private
private
def
full_project_path
(
namespace
,
project_ref
)
def
full_project_path
(
namespace
,
project_ref
)
return
current_parent_path
unless
project_ref
return
current_parent_path
unless
project_ref
namespace_ref
=
namespace
||
current_project_namespace_path
namespace_ref
=
namespace
||
current_project_namespace_path
"
#{
namespace_ref
}
/
#{
project_ref
}
"
"
#{
namespace_ref
}
/
#{
project_ref
}
"
end
end
def
refs_cache
def
refs_cache
Gitlab
::
SafeRequestStore
[
"banzai_
#{
parent_type
}
_refs"
.
to_sym
]
||=
{}
Gitlab
::
SafeRequestStore
[
"banzai_
#{
parent_type
}
_refs"
.
to_sym
]
||=
{}
end
end
def
parent_type
def
parent_type
:project
:project
end
end
def
parent
def
parent
parent_type
==
:project
?
project
:
group
parent_type
==
:project
?
project
:
group
end
end
def
full_group_path
(
group_ref
)
def
full_group_path
(
group_ref
)
return
current_parent_path
unless
group_ref
return
current_parent_path
unless
group_ref
group_ref
group_ref
end
end
def
unescape_html_entities
(
text
)
def
unescape_html_entities
(
text
)
CGI
.
unescapeHTML
(
text
.
to_s
)
CGI
.
unescapeHTML
(
text
.
to_s
)
end
end
def
escape_html_entities
(
text
)
def
escape_html_entities
(
text
)
CGI
.
escapeHTML
(
text
.
to_s
)
CGI
.
escapeHTML
(
text
.
to_s
)
end
end
def
escape_with_placeholders
(
text
,
placeholder_data
)
def
escape_with_placeholders
(
text
,
placeholder_data
)
escaped
=
escape_html_entities
(
text
)
escaped
=
escape_html_entities
(
text
)
escaped
.
gsub
(
REFERENCE_PLACEHOLDER_PATTERN
)
do
|
match
|
escaped
.
gsub
(
REFERENCE_PLACEHOLDER_PATTERN
)
do
|
match
|
placeholder_data
[
Regexp
.
last_match
(
1
).
to_i
]
placeholder_data
[
Regexp
.
last_match
(
1
).
to_i
]
end
end
end
end
end
end
end
end
end
end
end
Banzai
::
Filter
::
AbstractReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter
::AbstractReferenceFilter'
)
Banzai
::
Filter
::
References
::
AbstractReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter::References
::AbstractReferenceFilter'
)
lib/banzai/filter/references/alert_reference_filter.rb
View file @
7ecc247a
...
@@ -2,27 +2,29 @@
...
@@ -2,27 +2,29 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
class
AlertReferenceFilter
<
IssuableReferenceFilter
module
References
self
.
reference_type
=
:alert
class
AlertReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:alert
def
self
.
object_class
def
self
.
object_class
AlertManagement
::
Alert
AlertManagement
::
Alert
end
end
def
self
.
object_sym
def
self
.
object_sym
:alert
:alert
end
end
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
alert_management_alerts
.
where
(
iid:
ids
.
to_a
)
parent
.
alert_management_alerts
.
where
(
iid:
ids
.
to_a
)
end
end
def
url_for_object
(
alert
,
project
)
def
url_for_object
(
alert
,
project
)
::
Gitlab
::
Routing
.
url_helpers
.
details_project_alert_management_url
(
::
Gitlab
::
Routing
.
url_helpers
.
details_project_alert_management_url
(
project
,
project
,
alert
.
iid
,
alert
.
iid
,
only_path:
context
[
:only_path
]
only_path:
context
[
:only_path
]
)
)
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/commit_range_reference_filter.rb
View file @
7ecc247a
...
@@ -2,44 +2,46 @@
...
@@ -2,44 +2,46 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces commit range references with links.
module
References
#
# HTML filter that replaces commit range references with links.
# This filter supports cross-project references.
#
class
CommitRangeReferenceFilter
<
AbstractReferenceFilter
# This filter supports cross-project references.
self
.
reference_type
=
:commit_range
class
CommitRangeReferenceFilter
<
AbstractReferenceFilter
self
.
reference_type
=
:commit_range
def
self
.
object_class
CommitRange
def
self
.
object_class
end
CommitRange
end
def
self
.
references_in
(
text
,
pattern
=
CommitRange
.
reference_pattern
)
def
self
.
references_in
(
text
,
pattern
=
CommitRange
.
reference_pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
text
.
gsub
(
pattern
)
do
|
match
|
yield
match
,
$~
[
:commit_range
],
$~
[
:project
],
$~
[
:namespace
],
$~
yield
match
,
$~
[
:commit_range
],
$~
[
:project
],
$~
[
:namespace
],
$~
end
end
end
end
def
initialize
(
*
args
)
def
initialize
(
*
args
)
super
super
@commit_map
=
{}
@commit_map
=
{}
end
end
def
find_object
(
project
,
id
)
def
find_object
(
project
,
id
)
return
unless
project
.
is_a?
(
Project
)
return
unless
project
.
is_a?
(
Project
)
range
=
CommitRange
.
new
(
id
,
project
)
range
=
CommitRange
.
new
(
id
,
project
)
range
.
valid_commits?
?
range
:
nil
range
.
valid_commits?
?
range
:
nil
end
end
def
url_for_object
(
range
,
project
)
def
url_for_object
(
range
,
project
)
h
=
Gitlab
::
Routing
.
url_helpers
h
=
Gitlab
::
Routing
.
url_helpers
h
.
project_compare_url
(
project
,
h
.
project_compare_url
(
project
,
range
.
to_param
.
merge
(
only_path:
context
[
:only_path
]))
range
.
to_param
.
merge
(
only_path:
context
[
:only_path
]))
end
end
def
object_link_title
(
range
,
matches
)
def
object_link_title
(
range
,
matches
)
nil
nil
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/commit_reference_filter.rb
View file @
7ecc247a
...
@@ -2,84 +2,86 @@
...
@@ -2,84 +2,86 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces commit references with links.
module
References
#
# HTML filter that replaces commit references with links.
# This filter supports cross-project references.
#
class
CommitReferenceFilter
<
AbstractReferenceFilter
# This filter supports cross-project references.
self
.
reference_type
=
:commit
class
CommitReferenceFilter
<
AbstractReferenceFilter
self
.
reference_type
=
:commit
def
self
.
object_class
Commit
def
self
.
object_class
end
Commit
end
def
self
.
references_in
(
text
,
pattern
=
Commit
.
reference_pattern
)
def
self
.
references_in
(
text
,
pattern
=
Commit
.
reference_pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
text
.
gsub
(
pattern
)
do
|
match
|
yield
match
,
$~
[
:commit
],
$~
[
:project
],
$~
[
:namespace
],
$~
yield
match
,
$~
[
:commit
],
$~
[
:project
],
$~
[
:namespace
],
$~
end
end
end
end
def
find_object
(
project
,
id
)
def
find_object
(
project
,
id
)
return
unless
project
.
is_a?
(
Project
)
&&
project
.
valid_repo?
return
unless
project
.
is_a?
(
Project
)
&&
project
.
valid_repo?
_
,
record
=
records_per_parent
[
project
].
detect
{
|
k
,
_v
|
Gitlab
::
Git
.
shas_eql?
(
k
,
id
)
}
_
,
record
=
records_per_parent
[
project
].
detect
{
|
k
,
_v
|
Gitlab
::
Git
.
shas_eql?
(
k
,
id
)
}
record
record
end
end
def
referenced_merge_request_commit_shas
def
referenced_merge_request_commit_shas
return
[]
unless
noteable
.
is_a?
(
MergeRequest
)
return
[]
unless
noteable
.
is_a?
(
MergeRequest
)
@referenced_merge_request_commit_shas
||=
begin
@referenced_merge_request_commit_shas
||=
begin
referenced_shas
=
references_per_parent
.
values
.
reduce
(
:|
).
to_a
referenced_shas
=
references_per_parent
.
values
.
reduce
(
:|
).
to_a
noteable
.
all_commit_shas
.
select
do
|
sha
|
noteable
.
all_commit_shas
.
select
do
|
sha
|
referenced_shas
.
any?
{
|
ref
|
Gitlab
::
Git
.
shas_eql?
(
sha
,
ref
)
}
referenced_shas
.
any?
{
|
ref
|
Gitlab
::
Git
.
shas_eql?
(
sha
,
ref
)
}
end
end
end
end
end
end
# The default behaviour is `#to_i` - we just pass the hash through.
# The default behaviour is `#to_i` - we just pass the hash through.
def
self
.
parse_symbol
(
sha_hash
,
_match
)
def
self
.
parse_symbol
(
sha_hash
,
_match
)
sha_hash
sha_hash
end
end
def
url_for_object
(
commit
,
project
)
def
url_for_object
(
commit
,
project
)
h
=
Gitlab
::
Routing
.
url_helpers
h
=
Gitlab
::
Routing
.
url_helpers
if
referenced_merge_request_commit_shas
.
include?
(
commit
.
id
)
if
referenced_merge_request_commit_shas
.
include?
(
commit
.
id
)
h
.
diffs_project_merge_request_url
(
project
,
h
.
diffs_project_merge_request_url
(
project
,
noteable
,
noteable
,
commit_id:
commit
.
id
,
commit_id:
commit
.
id
,
only_path:
only_path?
)
only_path:
only_path?
)
else
else
h
.
project_commit_url
(
project
,
h
.
project_commit_url
(
project
,
commit
,
commit
,
only_path:
only_path?
)
only_path:
only_path?
)
end
end
end
end
def
object_link_text_extras
(
object
,
matches
)
def
object_link_text_extras
(
object
,
matches
)
extras
=
super
extras
=
super
path
=
matches
[
:path
]
if
matches
.
names
.
include?
(
"path"
)
path
=
matches
[
:path
]
if
matches
.
names
.
include?
(
"path"
)
if
path
==
'/builds'
if
path
==
'/builds'
extras
.
unshift
"builds"
extras
.
unshift
"builds"
end
end
extras
extras
end
end
private
private
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
commits_by
(
oids:
ids
.
to_a
)
parent
.
commits_by
(
oids:
ids
.
to_a
)
end
end
def
noteable
def
noteable
context
[
:noteable
]
context
[
:noteable
]
end
end
def
only_path?
def
only_path?
context
[
:only_path
]
context
[
:only_path
]
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/design_reference_filter.rb
View file @
7ecc247a
...
@@ -2,105 +2,107 @@
...
@@ -2,105 +2,107 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
class
DesignReferenceFilter
<
AbstractReferenceFilter
module
References
class
Identifier
class
DesignReferenceFilter
<
AbstractReferenceFilter
include
Comparable
class
Identifier
attr_reader
:issue_iid
,
:filename
include
Comparable
attr_reader
:issue_iid
,
:filename
def
initialize
(
issue_iid
:,
filename
:)
@issue_iid
=
issue_iid
def
initialize
(
issue_iid
:,
filename
:)
@filename
=
filename
@issue_iid
=
issue_iid
@filename
=
filename
end
def
as_composite_id
(
id_for_iid
)
id
=
id_for_iid
[
issue_iid
]
return
unless
id
{
issue_id:
id
,
filename:
filename
}
end
def
<
=>
(
other
)
return
unless
other
.
is_a?
(
Identifier
)
[
issue_iid
,
filename
]
<=>
[
other
.
issue_iid
,
other
.
filename
]
end
alias_method
:eql?
,
:==
def
hash
[
issue_iid
,
filename
].
hash
end
end
end
def
as_composite_id
(
id_for_iid
)
self
.
reference_type
=
:design
id
=
id_for_iid
[
issue_iid
]
return
unless
id
{
issue_id:
id
,
filename:
filename
}
def
find_object
(
project
,
identifier
)
records_per_parent
[
project
][
identifier
]
end
end
def
<
=>
(
other
)
def
parent_records
(
project
,
identifiers
)
return
unless
other
.
is_a?
(
Identifier
)
return
[]
unless
project
.
design_management_enabled?
[
issue_iid
,
filename
]
<=>
[
other
.
issue_iid
,
other
.
filename
]
iids
=
identifiers
.
map
(
&
:issue_iid
).
to_set
end
issues
=
project
.
issues
.
where
(
iid:
iids
)
alias_method
:eql?
,
:==
id_for_iid
=
issues
.
index_by
(
&
:iid
).
transform_values
(
&
:id
)
issue_by_id
=
issues
.
index_by
(
&
:id
)
def
hash
designs
(
identifiers
,
id_for_iid
).
each
do
|
d
|
[
issue_iid
,
filename
].
hash
issue
=
issue_by_id
[
d
.
issue_id
]
# optimisation: assign values we have already fetched
d
.
project
=
project
d
.
issue
=
issue
end
end
end
end
self
.
reference_type
=
:design
def
find_object
(
project
,
identifier
)
records_per_parent
[
project
][
identifier
]
end
def
parent_records
(
project
,
identifiers
)
return
[]
unless
project
.
design_management_enabled?
iids
=
identifiers
.
map
(
&
:issue_iid
).
to_set
issues
=
project
.
issues
.
where
(
iid:
iids
)
id_for_iid
=
issues
.
index_by
(
&
:iid
).
transform_values
(
&
:id
)
issue_by_id
=
issues
.
index_by
(
&
:id
)
designs
(
identifiers
,
id_for_iid
).
each
do
|
d
|
def
relation_for_paths
(
paths
)
issue
=
issue_by_id
[
d
.
issue_id
]
super
.
includes
(
:route
,
:namespace
,
:group
)
# optimisation: assign values we have already fetched
d
.
project
=
project
d
.
issue
=
issue
end
end
end
def
relation_for_paths
(
paths
)
super
.
includes
(
:route
,
:namespace
,
:group
)
end
def
parent_type
def
parent_type
:project
:project
end
end
# optimisation to reuse the parent_per_reference query information
# optimisation to reuse the parent_per_reference query information
def
parent_from_ref
(
ref
)
def
parent_from_ref
(
ref
)
parent_per_reference
[
ref
||
current_parent_path
]
parent_per_reference
[
ref
||
current_parent_path
]
end
end
def
url_for_object
(
design
,
project
)
def
url_for_object
(
design
,
project
)
path_options
=
{
vueroute:
design
.
filename
}
path_options
=
{
vueroute:
design
.
filename
}
Gitlab
::
Routing
.
url_helpers
.
designs_project_issue_path
(
project
,
design
.
issue
,
path_options
)
Gitlab
::
Routing
.
url_helpers
.
designs_project_issue_path
(
project
,
design
.
issue
,
path_options
)
end
end
def
data_attributes_for
(
_text
,
_project
,
design
,
**
_kwargs
)
def
data_attributes_for
(
_text
,
_project
,
design
,
**
_kwargs
)
super
.
merge
(
issue:
design
.
issue_id
)
super
.
merge
(
issue:
design
.
issue_id
)
end
end
def
self
.
object_class
def
self
.
object_class
::
DesignManagement
::
Design
::
DesignManagement
::
Design
end
end
def
self
.
object_sym
def
self
.
object_sym
:design
:design
end
end
def
self
.
parse_symbol
(
raw
,
match_data
)
def
self
.
parse_symbol
(
raw
,
match_data
)
filename
=
match_data
[
:url_filename
]
filename
=
match_data
[
:url_filename
]
iid
=
match_data
[
:issue
].
to_i
iid
=
match_data
[
:issue
].
to_i
Identifier
.
new
(
filename:
CGI
.
unescape
(
filename
),
issue_iid:
iid
)
Identifier
.
new
(
filename:
CGI
.
unescape
(
filename
),
issue_iid:
iid
)
end
end
def
record_identifier
(
design
)
def
record_identifier
(
design
)
Identifier
.
new
(
filename:
design
.
filename
,
issue_iid:
design
.
issue
.
iid
)
Identifier
.
new
(
filename:
design
.
filename
,
issue_iid:
design
.
issue
.
iid
)
end
end
private
private
def
designs
(
identifiers
,
id_for_iid
)
def
designs
(
identifiers
,
id_for_iid
)
identifiers
identifiers
.
map
{
|
identifier
|
identifier
.
as_composite_id
(
id_for_iid
)
}
.
map
{
|
identifier
|
identifier
.
as_composite_id
(
id_for_iid
)
}
.
compact
.
compact
.
in_groups_of
(
100
,
false
)
# limitation of by_issue_id_and_filename, so we batch
.
in_groups_of
(
100
,
false
)
# limitation of by_issue_id_and_filename, so we batch
.
flat_map
{
|
ids
|
DesignManagement
::
Design
.
by_issue_id_and_filename
(
ids
)
}
.
flat_map
{
|
ids
|
DesignManagement
::
Design
.
by_issue_id_and_filename
(
ids
)
}
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/epic_reference_filter.rb
View file @
7ecc247a
...
@@ -2,21 +2,23 @@
...
@@ -2,21 +2,23 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# The actual filter is implemented in the EE mixin
module
References
class
EpicReferenceFilter
<
IssuableReferenceFilter
# The actual filter is implemented in the EE mixin
self
.
reference_type
=
:epic
class
EpicReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:epic
def
self
.
object_class
def
self
.
object_class
Epic
Epic
end
end
private
private
def
group
def
group
context
[
:group
]
||
context
[
:project
]
&
.
group
context
[
:group
]
||
context
[
:project
]
&
.
group
end
end
end
end
end
end
end
end
end
Banzai
::
Filter
::
EpicReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter
::EpicReferenceFilter'
)
Banzai
::
Filter
::
References
::
EpicReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter::References
::EpicReferenceFilter'
)
lib/banzai/filter/references/external_issue_reference_filter.rb
View file @
7ecc247a
...
@@ -2,116 +2,118 @@
...
@@ -2,116 +2,118 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces external issue tracker references with links.
module
References
# References are ignored if the project doesn't use an external issue
# HTML filter that replaces external issue tracker references with links.
# tracker.
# References are ignored if the project doesn't use an external issue
#
# tracker.
# This filter does not support cross-project references.
class
ExternalIssueReferenceFilter
<
ReferenceFilter
self
.
reference_type
=
:external_issue
# Public: Find `JIRA-123` issue references in text
#
#
# ExternalIssueReferenceFilter.references_in(text, pattern) do |match, issue|
# This filter does not support cross-project references.
# "<a href=...>##{issue}</a>"
class
ExternalIssueReferenceFilter
<
ReferenceFilter
# end
self
.
reference_type
=
:external_issue
#
# text - String text to search.
# Public: Find `JIRA-123` issue references in text
#
#
# Yields the String match and the String issue reference.
# ExternalIssueReferenceFilter.references_in(text, pattern) do |match, issue|
#
# "<a href=...>##{issue}</a>"
# Returns a String replaced with the return of the block.
# end
def
self
.
references_in
(
text
,
pattern
)
#
text
.
gsub
(
pattern
)
do
|
match
|
# text - String text to search.
yield
match
,
$~
[
:issue
]
#
# Yields the String match and the String issue reference.
#
# Returns a String replaced with the return of the block.
def
self
.
references_in
(
text
,
pattern
)
text
.
gsub
(
pattern
)
do
|
match
|
yield
match
,
$~
[
:issue
]
end
end
end
end
def
call
def
call
# Early return if the project isn't using an external tracker
# Early return if the project isn't using an external tracker
return
doc
if
project
.
nil?
||
default_issues_tracker?
return
doc
if
project
.
nil?
||
default_issues_tracker?
ref_pattern
=
issue_reference_pattern
ref_pattern
=
issue_reference_pattern
ref_start_pattern
=
/\A
#{
ref_pattern
}
\z/
ref_start_pattern
=
/\A
#{
ref_pattern
}
\z/
nodes
.
each_with_index
do
|
node
,
index
|
nodes
.
each_with_index
do
|
node
,
index
|
if
text_node?
(
node
)
if
text_node?
(
node
)
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
issue_link_filter
(
content
)
issue_link_filter
(
content
)
end
end
elsif
element_node?
(
node
)
elsif
element_node?
(
node
)
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
if
link
=~
ref_start_pattern
if
link
=~
ref_start_pattern
replace_link_node_with_href
(
node
,
index
,
link
)
do
replace_link_node_with_href
(
node
,
index
,
link
)
do
issue_link_filter
(
link
,
link_content:
inner_html
)
issue_link_filter
(
link
,
link_content:
inner_html
)
end
end
end
end
end
end
end
end
end
end
doc
end
private
doc
end
# Replace `JIRA-123` issue references in text with links to the referenced
private
# issue's details page.
#
# Replace `JIRA-123` issue references in text with links to the referenced
# text - String text to replace references in.
# issue's details page.
# link_content - Original content of the link being replaced.
#
#
# text - String text to replace references in.
# Returns a String with `JIRA-123` references replaced with links. All
# link_content - Original content of the link being replaced.
# links have `gfm` and `gfm-issue` class names attached for styling.
#
def
issue_link_filter
(
text
,
link_content:
nil
)
# Returns a String with `JIRA-123` references replaced with links. All
self
.
class
.
references_in
(
text
,
issue_reference_pattern
)
do
|
match
,
id
|
# links have `gfm` and `gfm-issue` class names attached for styling.
url
=
url_for_issue
(
id
)
def
issue_link_filter
(
text
,
link_content:
nil
)
klass
=
reference_class
(
:issue
)
self
.
class
.
references_in
(
text
,
issue_reference_pattern
)
do
|
match
,
id
|
data
=
data_attribute
(
project:
project
.
id
,
external_issue:
id
)
url
=
url_for_issue
(
id
)
content
=
link_content
||
match
klass
=
reference_class
(
:issue
)
data
=
data_attribute
(
project:
project
.
id
,
external_issue:
id
)
%(<a href="#{url}" #{data}
content
=
link_content
||
match
title="#{escape_once(issue_title)}"
class="#{klass}">#{content}</a>)
%(<a href="#{url}" #{data}
title="#{escape_once(issue_title)}"
class="#{klass}">#{content}</a>)
end
end
end
end
def
url_for_issue
(
issue_id
)
def
url_for_issue
(
issue_id
)
return
''
if
project
.
nil?
return
''
if
project
.
nil?
url
=
if
only_path?
url
=
if
only_path?
project
.
external_issue_tracker
.
issue_path
(
issue_id
)
project
.
external_issue_tracker
.
issue_path
(
issue_id
)
else
else
project
.
external_issue_tracker
.
issue_url
(
issue_id
)
project
.
external_issue_tracker
.
issue_url
(
issue_id
)
end
end
# Ensure we return a valid URL to prevent possible XSS.
# Ensure we return a valid URL to prevent possible XSS.
URI
.
parse
(
url
).
to_s
URI
.
parse
(
url
).
to_s
rescue
URI
::
InvalidURIError
rescue
URI
::
InvalidURIError
''
''
end
end
def
default_issues_tracker?
def
default_issues_tracker?
external_issues_cached
(
:default_issues_tracker?
)
external_issues_cached
(
:default_issues_tracker?
)
end
end
def
issue_reference_pattern
def
issue_reference_pattern
external_issues_cached
(
:external_issue_reference_pattern
)
external_issues_cached
(
:external_issue_reference_pattern
)
end
end
def
project
def
project
context
[
:project
]
context
[
:project
]
end
end
def
issue_title
def
issue_title
"Issue in
#{
project
.
external_issue_tracker
.
title
}
"
"Issue in
#{
project
.
external_issue_tracker
.
title
}
"
end
end
def
external_issues_cached
(
attribute
)
def
external_issues_cached
(
attribute
)
cached_attributes
=
Gitlab
::
SafeRequestStore
[
:banzai_external_issues_tracker_attributes
]
||=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
{}
}
cached_attributes
=
Gitlab
::
SafeRequestStore
[
:banzai_external_issues_tracker_attributes
]
||=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
{}
}
cached_attributes
[
project
.
id
][
attribute
]
=
project
.
public_send
(
attribute
)
if
cached_attributes
[
project
.
id
][
attribute
].
nil?
# rubocop:disable GitlabSecurity/PublicSend
cached_attributes
[
project
.
id
][
attribute
]
=
project
.
public_send
(
attribute
)
if
cached_attributes
[
project
.
id
][
attribute
].
nil?
# rubocop:disable GitlabSecurity/PublicSend
cached_attributes
[
project
.
id
][
attribute
]
cached_attributes
[
project
.
id
][
attribute
]
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/feature_flag_reference_filter.rb
View file @
7ecc247a
...
@@ -2,31 +2,33 @@
...
@@ -2,31 +2,33 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
class
FeatureFlagReferenceFilter
<
IssuableReferenceFilter
module
References
self
.
reference_type
=
:feature_flag
class
FeatureFlagReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:feature_flag
def
self
.
object_class
def
self
.
object_class
Operations
::
FeatureFlag
Operations
::
FeatureFlag
end
end
def
self
.
object_sym
def
self
.
object_sym
:feature_flag
:feature_flag
end
end
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
operations_feature_flags
.
where
(
iid:
ids
.
to_a
)
parent
.
operations_feature_flags
.
where
(
iid:
ids
.
to_a
)
end
end
def
url_for_object
(
feature_flag
,
project
)
def
url_for_object
(
feature_flag
,
project
)
::
Gitlab
::
Routing
.
url_helpers
.
edit_project_feature_flag_url
(
::
Gitlab
::
Routing
.
url_helpers
.
edit_project_feature_flag_url
(
project
,
project
,
feature_flag
.
iid
,
feature_flag
.
iid
,
only_path:
context
[
:only_path
]
only_path:
context
[
:only_path
]
)
)
end
end
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
object
.
name
object
.
name
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/issuable_reference_filter.rb
View file @
7ecc247a
...
@@ -2,17 +2,19 @@
...
@@ -2,17 +2,19 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
class
IssuableReferenceFilter
<
AbstractReferenceFilter
module
References
def
record_identifier
(
record
)
class
IssuableReferenceFilter
<
AbstractReferenceFilter
record
.
iid
.
to_i
def
record_identifier
(
record
)
end
record
.
iid
.
to_i
end
def
find_object
(
parent
,
iid
)
def
find_object
(
parent
,
iid
)
records_per_parent
[
parent
][
iid
]
records_per_parent
[
parent
][
iid
]
end
end
def
parent_from_ref
(
ref
)
def
parent_from_ref
(
ref
)
parent_per_reference
[
ref
||
current_parent_path
]
parent_per_reference
[
ref
||
current_parent_path
]
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/issue_reference_filter.rb
View file @
7ecc247a
...
@@ -2,55 +2,57 @@
...
@@ -2,55 +2,57 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces issue references with links. References to
module
References
# issues that do not exist are ignored.
# HTML filter that replaces issue references with links. References to
#
# issues that do not exist are ignored.
# This filter supports cross-project references.
#
#
# This filter supports cross-project references.
# When external issues tracker like Jira is activated we should not
#
# use issue reference pattern, but we should still be able
# When external issues tracker like Jira is activated we should not
# to reference issues from other GitLab projects.
# use issue reference pattern, but we should still be able
class
IssueReferenceFilter
<
IssuableReferenceFilter
# to reference issues from other GitLab projects.
self
.
reference_type
=
:issue
class
IssueReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:issue
def
self
.
object_class
Issue
def
self
.
object_class
end
Issue
end
def
url_for_object
(
issue
,
project
)
def
url_for_object
(
issue
,
project
)
return
issue_path
(
issue
,
project
)
if
only_path?
return
issue_path
(
issue
,
project
)
if
only_path?
issue_url
(
issue
,
project
)
issue_url
(
issue
,
project
)
end
end
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
issues
.
where
(
iid:
ids
.
to_a
)
parent
.
issues
.
where
(
iid:
ids
.
to_a
)
end
end
def
object_link_text_extras
(
issue
,
matches
)
def
object_link_text_extras
(
issue
,
matches
)
super
+
design_link_extras
(
issue
,
matches
.
named_captures
[
'path'
])
super
+
design_link_extras
(
issue
,
matches
.
named_captures
[
'path'
])
end
end
private
private
def
issue_path
(
issue
,
project
)
def
issue_path
(
issue
,
project
)
Gitlab
::
Routing
.
url_helpers
.
namespace_project_issue_path
(
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
)
Gitlab
::
Routing
.
url_helpers
.
namespace_project_issue_path
(
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
)
end
end
def
issue_url
(
issue
,
project
)
def
issue_url
(
issue
,
project
)
Gitlab
::
Routing
.
url_helpers
.
namespace_project_issue_url
(
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
)
Gitlab
::
Routing
.
url_helpers
.
namespace_project_issue_url
(
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
)
end
end
def
design_link_extras
(
issue
,
path
)
def
design_link_extras
(
issue
,
path
)
if
path
==
'/designs'
&&
read_designs?
(
issue
)
if
path
==
'/designs'
&&
read_designs?
(
issue
)
[
'designs'
]
[
'designs'
]
else
else
[]
[]
end
end
end
end
def
read_designs?
(
issue
)
def
read_designs?
(
issue
)
issue
.
project
.
design_management_enabled?
issue
.
project
.
design_management_enabled?
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/iteration_reference_filter.rb
View file @
7ecc247a
...
@@ -2,15 +2,17 @@
...
@@ -2,15 +2,17 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# The actual filter is implemented in the EE mixin
module
References
class
IterationReferenceFilter
<
AbstractReferenceFilter
# The actual filter is implemented in the EE mixin
self
.
reference_type
=
:iteration
class
IterationReferenceFilter
<
AbstractReferenceFilter
self
.
reference_type
=
:iteration
def
self
.
object_class
def
self
.
object_class
Iteration
Iteration
end
end
end
end
end
end
end
end
end
Banzai
::
Filter
::
IterationReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter
::IterationReferenceFilter'
)
Banzai
::
Filter
::
References
::
IterationReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter::References
::IterationReferenceFilter'
)
lib/banzai/filter/references/label_reference_filter.rb
View file @
7ecc247a
...
@@ -2,128 +2,130 @@
...
@@ -2,128 +2,130 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces label references with links.
module
References
class
LabelReferenceFilter
<
AbstractReferenceFilter
# HTML filter that replaces label references with links.
self
.
reference_type
=
:label
class
LabelReferenceFilter
<
AbstractReferenceFilter
self
.
reference_type
=
:label
def
self
.
object_class
def
self
.
object_class
Label
Label
end
end
def
find_object
(
parent_object
,
id
)
find_labels
(
parent_object
).
find
(
id
)
end
def
references_in
(
text
,
pattern
=
Label
.
reference_pattern
)
labels
=
{}
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
namespace
,
project
=
$~
[
:namespace
],
$~
[
:project
]
project_path
=
full_project_path
(
namespace
,
project
)
label
=
find_label_cached
(
project_path
,
$~
[
:label_id
],
$~
[
:label_name
])
if
label
def
find_object
(
parent_object
,
id
)
labels
[
label
.
id
]
=
yield
match
,
label
.
id
,
project
,
namespace
,
$~
find_labels
(
parent_object
).
find
(
id
)
"
#{
REFERENCE_PLACEHOLDER
}#{
label
.
id
}
"
else
match
end
end
end
return
text
if
labels
.
empty?
def
references_in
(
text
,
pattern
=
Label
.
reference_pattern
)
labels
=
{}
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
namespace
,
project
=
$~
[
:namespace
],
$~
[
:project
]
project_path
=
full_project_path
(
namespace
,
project
)
label
=
find_label_cached
(
project_path
,
$~
[
:label_id
],
$~
[
:label_name
])
if
label
labels
[
label
.
id
]
=
yield
match
,
label
.
id
,
project
,
namespace
,
$~
"
#{
REFERENCE_PLACEHOLDER
}#{
label
.
id
}
"
else
match
end
end
escape_with_placeholders
(
unescaped_html
,
labels
)
return
text
if
labels
.
empty?
end
def
find_label_cached
(
parent_ref
,
label_id
,
label_name
)
escape_with_placeholders
(
unescaped_html
,
labels
)
cached_call
(
:banzai_find_label_cached
,
label_name
&
.
tr
(
'"'
,
''
)
||
label_id
,
path:
[
object_class
,
parent_ref
])
do
find_label
(
parent_ref
,
label_id
,
label_name
)
end
end
end
def
find_label
(
parent_ref
,
label_id
,
label_name
)
def
find_label_cached
(
parent_ref
,
label_id
,
label_name
)
parent
=
parent_from_ref
(
parent_ref
)
cached_call
(
:banzai_find_label_cached
,
label_name
&
.
tr
(
'"'
,
''
)
||
label_id
,
path:
[
object_class
,
parent_ref
])
do
return
unless
parent
find_label
(
parent_ref
,
label_id
,
label_name
)
end
end
label_params
=
label_params
(
label_id
,
label_name
)
def
find_label
(
parent_ref
,
label_id
,
label_name
)
find_labels
(
parent
).
find_by
(
label_params
)
parent
=
parent_from_ref
(
parent_ref
)
end
return
unless
parent
def
find_labels
(
parent
)
label_params
=
label_params
(
label_id
,
label_name
)
params
=
if
parent
.
is_a?
(
Group
)
find_labels
(
parent
).
find_by
(
label_params
)
{
group_id:
parent
.
id
,
end
include_ancestor_groups:
true
,
only_group_labels:
true
}
else
{
project:
parent
,
include_ancestor_groups:
true
}
end
LabelsFinder
.
new
(
nil
,
params
).
execute
(
skip_authorization:
true
)
end
# Parameters to pass to `Label.find_by` based on the given arguments
def
find_labels
(
parent
)
#
params
=
if
parent
.
is_a?
(
Group
)
# id - Integer ID to pass. If present, returns {id: id}
{
group_id:
parent
.
id
,
# name - String name to pass. If `id` is absent, finds by name without
include_ancestor_groups:
true
,
# surrounding quotes.
only_group_labels:
true
}
#
else
# Returns a Hash.
{
project:
parent
,
def
label_params
(
id
,
name
)
include_ancestor_groups:
true
}
if
name
end
{
name:
name
.
tr
(
'"'
,
''
)
}
else
LabelsFinder
.
new
(
nil
,
params
).
execute
(
skip_authorization:
true
)
{
id:
id
.
to_i
}
end
end
end
def
url_for_object
(
label
,
parent
)
# Parameters to pass to `Label.find_by` based on the given arguments
label_url_method
=
#
if
context
[
:label_url_method
]
# id - Integer ID to pass. If present, returns {id: id}
context
[
:label_url_method
]
# name - String name to pass. If `id` is absent, finds by name without
elsif
parent
.
is_a?
(
Project
)
# surrounding quotes.
:project_issues_url
#
# Returns a Hash.
def
label_params
(
id
,
name
)
if
name
{
name:
name
.
tr
(
'"'
,
''
)
}
else
{
id:
id
.
to_i
}
end
end
end
return
unless
label_url_method
def
url_for_object
(
label
,
parent
)
label_url_method
=
if
context
[
:label_url_method
]
context
[
:label_url_method
]
elsif
parent
.
is_a?
(
Project
)
:project_issues_url
end
Gitlab
::
Routing
.
url_helpers
.
public_send
(
label_url_method
,
parent
,
label_name:
label
.
name
,
only_path:
context
[
:only_path
])
# rubocop:disable GitlabSecurity/PublicSend
return
unless
label_url_method
end
def
object_link_text
(
object
,
matches
)
Gitlab
::
Routing
.
url_helpers
.
public_send
(
label_url_method
,
parent
,
label_name:
label
.
name
,
only_path:
context
[
:only_path
])
# rubocop:disable GitlabSecurity/PublicSend
label_suffix
=
''
end
parent
=
project
||
group
if
project
||
full_path_ref?
(
matches
)
def
object_link_text
(
object
,
matches
)
project_path
=
full_project_path
(
matches
[
:namespace
],
matches
[
:project
])
label_suffix
=
''
parent_from_ref
=
from_ref_cached
(
project_path
)
parent
=
project
||
group
reference
=
parent_from_ref
.
to_human_reference
(
parent
)
label_suffix
=
" <i>in
#{
ERB
::
Util
.
html_escape
(
reference
)
}
</i>"
if
reference
.
present?
if
project
||
full_path_ref?
(
matches
)
end
project_path
=
full_project_path
(
matches
[
:namespace
],
matches
[
:project
])
parent_from_ref
=
from_ref_cached
(
project_path
)
reference
=
parent_from_ref
.
to_human_reference
(
parent
)
presenter
=
object
.
present
(
issuable_subject:
parent
)
label_suffix
=
" <i>in
#{
ERB
::
Util
.
html_escape
(
reference
)
}
</i>"
if
reference
.
present?
LabelsHelper
.
render_colored_label
(
presenter
,
suffix:
label_suffix
)
end
end
def
wrap_link
(
link
,
label
)
presenter
=
object
.
present
(
issuable_subject:
parent
)
presenter
=
label
.
present
(
issuable_subject:
project
||
group
)
LabelsHelper
.
render_colored_label
(
presenter
,
suffix:
label_suffix
)
LabelsHelper
.
wrap_label_html
(
link
,
small:
true
,
label:
presenter
)
end
end
def
full_path_ref?
(
matches
)
def
wrap_link
(
link
,
label
)
matches
[
:namespace
]
&&
matches
[
:project
]
presenter
=
label
.
present
(
issuable_subject:
project
||
group
)
end
LabelsHelper
.
wrap_label_html
(
link
,
small:
true
,
label:
presenter
)
end
def
reference_class
(
type
,
tooltip:
true
)
def
full_path_ref?
(
matches
)
super
+
' gl-link gl-label-link'
matches
[
:namespace
]
&&
matches
[
:project
]
end
end
def
reference_class
(
type
,
tooltip:
true
)
super
+
' gl-link gl-label-link'
end
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
presenter
=
object
.
present
(
issuable_subject:
project
||
group
)
presenter
=
object
.
present
(
issuable_subject:
project
||
group
)
LabelsHelper
.
label_tooltip_title
(
presenter
)
LabelsHelper
.
label_tooltip_title
(
presenter
)
end
end
end
end
end
end
end
end
end
Banzai
::
Filter
::
LabelReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter
::LabelReferenceFilter'
)
Banzai
::
Filter
::
References
::
LabelReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter::References
::LabelReferenceFilter'
)
lib/banzai/filter/references/merge_request_reference_filter.rb
View file @
7ecc247a
...
@@ -2,95 +2,97 @@
...
@@ -2,95 +2,97 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces merge request references with links. References
module
References
# to merge requests that do not exist are ignored.
# HTML filter that replaces merge request references with links. References
#
# to merge requests that do not exist are ignored.
# This filter supports cross-project references.
#
class
MergeRequestReferenceFilter
<
IssuableReferenceFilter
# This filter supports cross-project references.
self
.
reference_type
=
:merge_request
class
MergeRequestReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:merge_request
def
self
.
object_class
MergeRequest
def
self
.
object_class
end
MergeRequest
end
def
url_for_object
(
mr
,
project
)
def
url_for_object
(
mr
,
project
)
h
=
Gitlab
::
Routing
.
url_helpers
h
=
Gitlab
::
Routing
.
url_helpers
h
.
project_merge_request_url
(
project
,
mr
,
h
.
project_merge_request_url
(
project
,
mr
,
only_path:
context
[
:only_path
])
only_path:
context
[
:only_path
])
end
end
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
# The method will return `nil` if object is not a commit
# The method will return `nil` if object is not a commit
# allowing for properly handling the extended MR Tooltip
# allowing for properly handling the extended MR Tooltip
object_link_commit_title
(
object
,
matches
)
object_link_commit_title
(
object
,
matches
)
end
end
def
object_link_text_extras
(
object
,
matches
)
def
object_link_text_extras
(
object
,
matches
)
extras
=
super
extras
=
super
if
commit_ref
=
object_link_commit_ref
(
object
,
matches
)
if
commit_ref
=
object_link_commit_ref
(
object
,
matches
)
klass
=
reference_class
(
:commit
,
tooltip:
false
)
klass
=
reference_class
(
:commit
,
tooltip:
false
)
commit_ref_tag
=
%(<span class="#{klass}">#{commit_ref}</span>)
commit_ref_tag
=
%(<span class="#{klass}">#{commit_ref}</span>)
return
extras
.
unshift
(
commit_ref_tag
)
return
extras
.
unshift
(
commit_ref_tag
)
end
end
path
=
matches
[
:path
]
if
matches
.
names
.
include?
(
"path"
)
path
=
matches
[
:path
]
if
matches
.
names
.
include?
(
"path"
)
case
path
case
path
when
'/diffs'
when
'/diffs'
extras
.
unshift
"diffs"
extras
.
unshift
"diffs"
when
'/commits'
when
'/commits'
extras
.
unshift
"commits"
extras
.
unshift
"commits"
when
'/builds'
when
'/builds'
extras
.
unshift
"builds"
extras
.
unshift
"builds"
end
end
extras
extras
end
end
def
parent_records
(
parent
,
ids
)
def
parent_records
(
parent
,
ids
)
parent
.
merge_requests
parent
.
merge_requests
.
where
(
iid:
ids
.
to_a
)
.
where
(
iid:
ids
.
to_a
)
.
includes
(
target_project: :namespace
)
.
includes
(
target_project: :namespace
)
end
end
def
reference_class
(
object_sym
,
options
=
{})
def
reference_class
(
object_sym
,
options
=
{})
super
(
object_sym
,
tooltip:
false
)
super
(
object_sym
,
tooltip:
false
)
end
end
def
data_attributes_for
(
text
,
parent
,
object
,
**
data
)
def
data_attributes_for
(
text
,
parent
,
object
,
**
data
)
super
.
merge
(
project_path:
parent
.
full_path
,
iid:
object
.
iid
,
mr_title:
object
.
title
)
super
.
merge
(
project_path:
parent
.
full_path
,
iid:
object
.
iid
,
mr_title:
object
.
title
)
end
end
private
private
def
object_link_commit_title
(
object
,
matches
)
def
object_link_commit_title
(
object
,
matches
)
object_link_commit
(
object
,
matches
)
&
.
title
object_link_commit
(
object
,
matches
)
&
.
title
end
end
def
object_link_commit_ref
(
object
,
matches
)
def
object_link_commit_ref
(
object
,
matches
)
object_link_commit
(
object
,
matches
)
&
.
short_id
object_link_commit
(
object
,
matches
)
&
.
short_id
end
end
def
object_link_commit
(
object
,
matches
)
def
object_link_commit
(
object
,
matches
)
return
unless
matches
.
names
.
include?
(
'query'
)
&&
query
=
matches
[
:query
]
return
unless
matches
.
names
.
include?
(
'query'
)
&&
query
=
matches
[
:query
]
# Removes leading "?". CGI.parse expects "arg1&arg2&arg3"
# Removes leading "?". CGI.parse expects "arg1&arg2&arg3"
params
=
CGI
.
parse
(
query
.
sub
(
/^\?/
,
''
))
params
=
CGI
.
parse
(
query
.
sub
(
/^\?/
,
''
))
return
unless
commit_sha
=
params
[
'commit_id'
]
&
.
first
return
unless
commit_sha
=
params
[
'commit_id'
]
&
.
first
if
commit
=
find_commit_by_sha
(
object
,
commit_sha
)
if
commit
=
find_commit_by_sha
(
object
,
commit_sha
)
Commit
.
from_hash
(
commit
.
to_hash
,
object
.
project
)
Commit
.
from_hash
(
commit
.
to_hash
,
object
.
project
)
end
end
end
end
def
find_commit_by_sha
(
object
,
commit_sha
)
def
find_commit_by_sha
(
object
,
commit_sha
)
@all_commits
||=
{}
@all_commits
||=
{}
@all_commits
[
object
.
id
]
||=
object
.
all_commits
@all_commits
[
object
.
id
]
||=
object
.
all_commits
@all_commits
[
object
.
id
].
find
{
|
commit
|
commit
.
sha
==
commit_sha
}
@all_commits
[
object
.
id
].
find
{
|
commit
|
commit
.
sha
==
commit_sha
}
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/milestone_reference_filter.rb
View file @
7ecc247a
...
@@ -2,136 +2,138 @@
...
@@ -2,136 +2,138 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces milestone references with links.
module
References
class
MilestoneReferenceFilter
<
AbstractReferenceFilter
# HTML filter that replaces milestone references with links.
include
Gitlab
::
Utils
::
StrongMemoize
class
MilestoneReferenceFilter
<
AbstractReferenceFilter
include
Gitlab
::
Utils
::
StrongMemoize
self
.
reference_type
=
:milestone
self
.
reference_type
=
:milestone
def
self
.
object_class
def
self
.
object_class
Milestone
Milestone
end
end
# Links to project milestones contain the IID, but when we're handling
# Links to project milestones contain the IID, but when we're handling
# 'regular' references, we need to use the global ID to disambiguate
# 'regular' references, we need to use the global ID to disambiguate
# between group and project milestones.
# between group and project milestones.
def
find_object
(
parent
,
id
)
def
find_object
(
parent
,
id
)
return
unless
valid_context?
(
parent
)
return
unless
valid_context?
(
parent
)
find_milestone_with_finder
(
parent
,
id:
id
)
find_milestone_with_finder
(
parent
,
id:
id
)
end
end
def
find_object_from_link
(
parent
,
iid
)
def
find_object_from_link
(
parent
,
iid
)
return
unless
valid_context?
(
parent
)
return
unless
valid_context?
(
parent
)
find_milestone_with_finder
(
parent
,
iid:
iid
)
find_milestone_with_finder
(
parent
,
iid:
iid
)
end
def
valid_context?
(
parent
)
strong_memoize
(
:valid_context
)
do
group_context?
(
parent
)
||
project_context?
(
parent
)
end
end
end
def
group_context?
(
parent
)
def
valid_context?
(
parent
)
strong_memoize
(
:group_context
)
do
strong_memoize
(
:valid_context
)
do
parent
.
is_a?
(
Group
)
group_context?
(
parent
)
||
project_context?
(
parent
)
end
end
end
end
def
project_context?
(
parent
)
def
group_context?
(
parent
)
strong_memoize
(
:project_context
)
do
strong_memoize
(
:group_context
)
do
parent
.
is_a?
(
Project
)
parent
.
is_a?
(
Group
)
end
end
end
end
def
references_in
(
text
,
pattern
=
Milestone
.
reference_pattern
)
# We'll handle here the references that follow the `reference_pattern`.
# Other patterns (for example, the link pattern) are handled by the
# default implementation.
return
super
(
text
,
pattern
)
if
pattern
!=
Milestone
.
reference_pattern
milestones
=
{}
def
project_context?
(
parent
)
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
strong_memoize
(
:project_context
)
do
milestone
=
find_milestone
(
$~
[
:project
],
$~
[
:namespace
],
$~
[
:milestone_iid
],
$~
[
:milestone_name
])
parent
.
is_a?
(
Project
)
if
milestone
milestones
[
milestone
.
id
]
=
yield
match
,
milestone
.
id
,
$~
[
:project
],
$~
[
:namespace
],
$~
"
#{
REFERENCE_PLACEHOLDER
}#{
milestone
.
id
}
"
else
match
end
end
end
end
return
text
if
milestones
.
empty?
def
references_in
(
text
,
pattern
=
Milestone
.
reference_pattern
)
# We'll handle here the references that follow the `reference_pattern`.
# Other patterns (for example, the link pattern) are handled by the
# default implementation.
return
super
(
text
,
pattern
)
if
pattern
!=
Milestone
.
reference_pattern
milestones
=
{}
unescaped_html
=
unescape_html_entities
(
text
).
gsub
(
pattern
)
do
|
match
|
milestone
=
find_milestone
(
$~
[
:project
],
$~
[
:namespace
],
$~
[
:milestone_iid
],
$~
[
:milestone_name
])
if
milestone
milestones
[
milestone
.
id
]
=
yield
match
,
milestone
.
id
,
$~
[
:project
],
$~
[
:namespace
],
$~
"
#{
REFERENCE_PLACEHOLDER
}#{
milestone
.
id
}
"
else
match
end
end
escape_with_placeholders
(
unescaped_html
,
milestones
)
return
text
if
milestones
.
empty?
end
def
find_milestone
(
project_ref
,
namespace_ref
,
milestone_id
,
milestone_name
)
escape_with_placeholders
(
unescaped_html
,
milestones
)
project_path
=
full_project_path
(
namespace_ref
,
project_ref
)
end
# Returns group if project is not found by path
def
find_milestone
(
project_ref
,
namespace_ref
,
milestone_id
,
milestone_name
)
parent
=
parent_from_ref
(
project_path
)
project_path
=
full_project_path
(
namespace_ref
,
project_ref
)
return
unless
parent
# Returns group if project is not found by path
parent
=
parent_from_ref
(
project_path
)
milestone_params
=
milestone_params
(
milestone_id
,
milestone_name
)
return
unless
parent
find_milestone_with_finder
(
parent
,
milestone_params
)
milestone_params
=
milestone_params
(
milestone_id
,
milestone_name
)
end
def
milestone_params
(
iid
,
name
)
find_milestone_with_finder
(
parent
,
milestone_params
)
if
name
{
name:
name
.
tr
(
'"'
,
''
)
}
else
{
iid:
iid
.
to_i
}
end
end
end
def
find_milestone_with_finder
(
parent
,
params
)
def
milestone_params
(
iid
,
name
)
finder_params
=
milestone_finder_params
(
parent
,
params
[
:iid
].
present?
)
if
name
{
name:
name
.
tr
(
'"'
,
''
)
}
else
{
iid:
iid
.
to_i
}
end
end
MilestonesFinder
.
new
(
finder_params
).
find_by
(
params
)
def
find_milestone_with_finder
(
parent
,
params
)
end
finder_params
=
milestone_finder_params
(
parent
,
params
[
:iid
].
present?
)
def
milestone_finder_params
(
parent
,
find_by_iid
)
MilestonesFinder
.
new
(
finder_params
).
find_by
(
params
)
{
order:
nil
,
state:
'all'
}.
tap
do
|
params
|
end
params
[
:project_ids
]
=
parent
.
id
if
project_context?
(
parent
)
def
milestone_finder_params
(
parent
,
find_by_iid
)
{
order:
nil
,
state:
'all'
}.
tap
do
|
params
|
params
[
:project_ids
]
=
parent
.
id
if
project_context?
(
parent
)
# We don't support IID lookups because IIDs can clash between
# We don't support IID lookups because IIDs can clash between
# group/project milestones and group/subgroup milestones.
# group/project milestones and group/subgroup milestones.
params
[
:group_ids
]
=
self_and_ancestors_ids
(
parent
)
unless
find_by_iid
params
[
:group_ids
]
=
self_and_ancestors_ids
(
parent
)
unless
find_by_iid
end
end
end
end
def
self_and_ancestors_ids
(
parent
)
def
self_and_ancestors_ids
(
parent
)
if
group_context?
(
parent
)
if
group_context?
(
parent
)
parent
.
self_and_ancestors
.
select
(
:id
)
parent
.
self_and_ancestors
.
select
(
:id
)
elsif
project_context?
(
parent
)
elsif
project_context?
(
parent
)
parent
.
group
&
.
self_and_ancestors
&
.
select
(
:id
)
parent
.
group
&
.
self_and_ancestors
&
.
select
(
:id
)
end
end
end
end
def
url_for_object
(
milestone
,
project
)
def
url_for_object
(
milestone
,
project
)
Gitlab
::
Routing
Gitlab
::
Routing
.
url_helpers
.
url_helpers
.
milestone_url
(
milestone
,
only_path:
context
[
:only_path
])
.
milestone_url
(
milestone
,
only_path:
context
[
:only_path
])
end
end
def
object_link_text
(
object
,
matches
)
def
object_link_text
(
object
,
matches
)
milestone_link
=
escape_once
(
super
)
milestone_link
=
escape_once
(
super
)
reference
=
object
.
project
&
.
to_reference_base
(
project
)
reference
=
object
.
project
&
.
to_reference_base
(
project
)
if
reference
.
present?
if
reference
.
present?
"
#{
milestone_link
}
<i>in
#{
reference
}
</i>"
.
html_safe
"
#{
milestone_link
}
<i>in
#{
reference
}
</i>"
.
html_safe
else
else
milestone_link
milestone_link
end
end
end
end
def
object_link_title
(
object
,
matches
)
def
object_link_title
(
object
,
matches
)
nil
nil
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/project_reference_filter.rb
View file @
7ecc247a
...
@@ -2,115 +2,117 @@
...
@@ -2,115 +2,117 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces project references with links.
module
References
class
ProjectReferenceFilter
<
ReferenceFilter
# HTML filter that replaces project references with links.
self
.
reference_type
=
:project
class
ProjectReferenceFilter
<
ReferenceFilter
self
.
reference_type
=
:project
# Public: Find `namespace/project>` project references in text
#
# Public: Find `namespace/project>` project references in text
# ProjectReferenceFilter.references_in(text) do |match, project|
#
# "<a href=...>#{project}></a>"
# ProjectReferenceFilter.references_in(text) do |match, project|
# end
# "<a href=...>#{project}></a>"
#
# end
# text - String text to search.
#
#
# text - String text to search.
# Yields the String match, and the String project name.
#
#
# Yields the String match, and the String project name.
# Returns a String replaced with the return of the block.
#
def
self
.
references_in
(
text
)
# Returns a String replaced with the return of the block.
text
.
gsub
(
Project
.
markdown_reference_pattern
)
do
|
match
|
def
self
.
references_in
(
text
)
yield
match
,
"
#{
$~
[
:namespace
]
}
/
#{
$~
[
:project
]
}
"
text
.
gsub
(
Project
.
markdown_reference_pattern
)
do
|
match
|
yield
match
,
"
#{
$~
[
:namespace
]
}
/
#{
$~
[
:project
]
}
"
end
end
end
end
def
call
def
call
ref_pattern
=
Project
.
markdown_reference_pattern
ref_pattern
=
Project
.
markdown_reference_pattern
ref_pattern_start
=
/\A
#{
ref_pattern
}
\z/
ref_pattern_start
=
/\A
#{
ref_pattern
}
\z/
nodes
.
each_with_index
do
|
node
,
index
|
nodes
.
each_with_index
do
|
node
,
index
|
if
text_node?
(
node
)
if
text_node?
(
node
)
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
project_link_filter
(
content
)
project_link_filter
(
content
)
end
end
elsif
element_node?
(
node
)
elsif
element_node?
(
node
)
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
if
link
=~
ref_pattern_start
if
link
=~
ref_pattern_start
replace_link_node_with_href
(
node
,
index
,
link
)
do
replace_link_node_with_href
(
node
,
index
,
link
)
do
project_link_filter
(
link
,
link_content:
inner_html
)
project_link_filter
(
link
,
link_content:
inner_html
)
end
end
end
end
end
end
end
end
end
end
doc
doc
end
end
# Replace `namespace/project>` project references in text with links to the referenced
# Replace `namespace/project>` project references in text with links to the referenced
# project page.
# project page.
#
#
# text - String text to replace references in.
# text - String text to replace references in.
# link_content - Original content of the link being replaced.
# link_content - Original content of the link being replaced.
#
#
# Returns a String with `namespace/project>` references replaced with links. All links
# Returns a String with `namespace/project>` references replaced with links. All links
# have `gfm` and `gfm-project` class names attached for styling.
# have `gfm` and `gfm-project` class names attached for styling.
def
project_link_filter
(
text
,
link_content:
nil
)
def
project_link_filter
(
text
,
link_content:
nil
)
self
.
class
.
references_in
(
text
)
do
|
match
,
project_path
|
self
.
class
.
references_in
(
text
)
do
|
match
,
project_path
|
cached_call
(
:banzai_url_for_object
,
match
,
path:
[
Project
,
project_path
.
downcase
])
do
cached_call
(
:banzai_url_for_object
,
match
,
path:
[
Project
,
project_path
.
downcase
])
do
if
project
=
projects_hash
[
project_path
.
downcase
]
if
project
=
projects_hash
[
project_path
.
downcase
]
link_to_project
(
project
,
link_content:
link_content
)
||
match
link_to_project
(
project
,
link_content:
link_content
)
||
match
else
else
match
match
end
end
end
end
end
end
end
end
# Returns a Hash containing all Project objects for the project
# Returns a Hash containing all Project objects for the project
# references in the current document.
# references in the current document.
#
#
# The keys of this Hash are the project paths, the values the
# The keys of this Hash are the project paths, the values the
# corresponding Project objects.
# corresponding Project objects.
def
projects_hash
def
projects_hash
@projects
||=
Project
.
eager_load
(
:route
,
namespace:
[
:route
])
@projects
||=
Project
.
eager_load
(
:route
,
namespace:
[
:route
])
.
where_full_path_in
(
projects
)
.
where_full_path_in
(
projects
)
.
index_by
(
&
:full_path
)
.
index_by
(
&
:full_path
)
.
transform_keys
(
&
:downcase
)
.
transform_keys
(
&
:downcase
)
end
end
# Returns all projects referenced in the current document.
# Returns all projects referenced in the current document.
def
projects
def
projects
refs
=
Set
.
new
refs
=
Set
.
new
nodes
.
each
do
|
node
|
nodes
.
each
do
|
node
|
node
.
to_html
.
scan
(
Project
.
markdown_reference_pattern
)
do
node
.
to_html
.
scan
(
Project
.
markdown_reference_pattern
)
do
refs
<<
"
#{
$~
[
:namespace
]
}
/
#{
$~
[
:project
]
}
"
refs
<<
"
#{
$~
[
:namespace
]
}
/
#{
$~
[
:project
]
}
"
end
end
end
end
refs
.
to_a
refs
.
to_a
end
end
private
private
def
urls
def
urls
Gitlab
::
Routing
.
url_helpers
Gitlab
::
Routing
.
url_helpers
end
end
def
link_class
def
link_class
reference_class
(
:project
)
reference_class
(
:project
)
end
end
def
link_to_project
(
project
,
link_content:
nil
)
def
link_to_project
(
project
,
link_content:
nil
)
url
=
urls
.
project_url
(
project
,
only_path:
context
[
:only_path
])
url
=
urls
.
project_url
(
project
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
project:
project
.
id
)
data
=
data_attribute
(
project:
project
.
id
)
content
=
link_content
||
project
.
to_reference
content
=
link_content
||
project
.
to_reference
link_tag
(
url
,
data
,
content
,
project
.
name
)
link_tag
(
url
,
data
,
content
,
project
.
name
)
end
end
def
link_tag
(
url
,
data
,
link_content
,
title
)
def
link_tag
(
url
,
data
,
link_content
,
title
)
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/reference_filter.rb
View file @
7ecc247a
...
@@ -3,212 +3,214 @@
...
@@ -3,212 +3,214 @@
# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/reference.js
# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/reference.js
module
Banzai
module
Banzai
module
Filter
module
Filter
# Base class for GitLab Flavored Markdown reference filters.
module
References
#
# Base class for GitLab Flavored Markdown reference filters.
# References within <pre>, <code>, <a>, and <style> elements are ignored.
#
# Context options:
# :project (required) - Current project, ignored if reference is cross-project.
# :only_path - Generate path-only links.
class
ReferenceFilter
<
HTML
::
Pipeline
::
Filter
include
RequestStoreReferenceCache
include
OutputSafety
class
<<
self
attr_accessor
:reference_type
def
call
(
doc
,
context
=
nil
,
result
=
nil
)
new
(
doc
,
context
,
result
).
call_and_update_nodes
end
end
def
initialize
(
doc
,
context
=
nil
,
result
=
nil
)
super
@new_nodes
=
{}
@nodes
=
self
.
result
[
:reference_filter_nodes
]
end
def
call_and_update_nodes
with_update_nodes
{
call
}
end
# Returns a data attribute String to attach to a reference link
#
#
# attributes - Hash, where the key becomes the data attribute name and the
# References within <pre>, <code>, <a>, and <style> elements are ignored.
# value is the data attribute value
#
#
# Examples:
# Context options:
#
# :project (required) - Current project, ignored if reference is cross-project.
# data_attribute(project: 1, issue: 2)
# :only_path - Generate path-only links.
# # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"1\" data-issue=\"2\""
class
ReferenceFilter
<
HTML
::
Pipeline
::
Filter
#
include
RequestStoreReferenceCache
# data_attribute(project: 3, merge_request: 4)
include
OutputSafety
# # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"3\" data-merge-request=\"4\""
#
class
<<
self
# Returns a String
attr_accessor
:reference_type
def
data_attribute
(
attributes
=
{})
attributes
=
attributes
.
reject
{
|
_
,
v
|
v
.
nil?
}
def
call
(
doc
,
context
=
nil
,
result
=
nil
)
new
(
doc
,
context
,
result
).
call_and_update_nodes
attributes
[
:reference_type
]
||=
self
.
class
.
reference_type
end
attributes
[
:container
]
||=
'body'
end
attributes
[
:placement
]
||=
'top'
attributes
.
delete
(
:original
)
if
context
[
:no_original_data
]
attributes
.
map
do
|
key
,
value
|
%Q(data-
#{
key
.
to_s
.
dasherize
}
="
#{
escape_once
(
value
)
}
")
end
.
join
(
' '
)
end
def
ignore_ancestor_query
def
initialize
(
doc
,
context
=
nil
,
result
=
nil
)
@ignore_ancestor_query
||=
begin
super
parents
=
%w(pre code a style)
parents
<<
'blockquote'
if
context
[
:ignore_blockquotes
]
parents
.
map
{
|
n
|
"ancestor::
#{
n
}
"
}.
join
(
' or '
)
@new_nodes
=
{}
@nodes
=
self
.
result
[
:reference_filter_nodes
]
end
end
end
def
project
def
call_and_update_nodes
context
[
:project
]
with_update_nodes
{
call
}
end
end
def
group
# Returns a data attribute String to attach to a reference link
context
[
:group
]
#
end
# attributes - Hash, where the key becomes the data attribute name and the
# value is the data attribute value
#
# Examples:
#
# data_attribute(project: 1, issue: 2)
# # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"1\" data-issue=\"2\""
#
# data_attribute(project: 3, merge_request: 4)
# # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"3\" data-merge-request=\"4\""
#
# Returns a String
def
data_attribute
(
attributes
=
{})
attributes
=
attributes
.
reject
{
|
_
,
v
|
v
.
nil?
}
attributes
[
:reference_type
]
||=
self
.
class
.
reference_type
attributes
[
:container
]
||=
'body'
attributes
[
:placement
]
||=
'top'
attributes
.
delete
(
:original
)
if
context
[
:no_original_data
]
attributes
.
map
do
|
key
,
value
|
%Q(data-
#{
key
.
to_s
.
dasherize
}
="
#{
escape_once
(
value
)
}
")
end
.
join
(
' '
)
end
def
user
def
ignore_ancestor_query
context
[
:user
]
@ignore_ancestor_query
||=
begin
end
parents
=
%w(pre code a style)
parents
<<
'blockquote'
if
context
[
:ignore_blockquotes
]
def
skip_project_check?
parents
.
map
{
|
n
|
"ancestor::
#{
n
}
"
}.
join
(
' or '
)
context
[
:skip_project_check
]
end
end
end
def
reference_class
(
type
,
tooltip:
true
)
def
project
gfm_klass
=
"gfm gfm-
#{
type
}
"
context
[
:project
]
end
return
gfm_klass
unless
tooltip
def
group
context
[
:group
]
end
"
#{
gfm_klass
}
has-tooltip"
def
user
end
context
[
:user
]
end
# Ensure that a :project key exists in context
def
skip_project_check?
#
context
[
:skip_project_check
]
# Note that while the key might exist, its value could be nil!
end
def
validate
needs
:project
unless
skip_project_check?
end
# Iterates over all <a> and text() nodes in a document.
def
reference_class
(
type
,
tooltip:
true
)
#
gfm_klass
=
"gfm gfm-
#{
type
}
"
# Nodes are skipped whenever their ancestor is one of the nodes returned
# by `ignore_ancestor_query`. Link tags are not processed if they have a
# "gfm" class or the "href" attribute is empty.
def
each_node
return
to_enum
(
__method__
)
unless
block_given?
doc
.
xpath
(
query
).
each
do
|
node
|
return
gfm_klass
unless
tooltip
yield
node
end
end
# Returns an Array containing all HTML nodes.
"
#{
gfm_klass
}
has-tooltip"
def
nodes
end
@nodes
||=
each_node
.
to_a
end
# Yields the link's URL and inner HTML whenever the node is a valid <a> tag.
# Ensure that a :project key exists in context
def
yield_valid_link
(
node
)
#
link
=
unescape_link
(
node
.
attr
(
'href'
).
to_s
)
# Note that while the key might exist, its value could be nil!
inner_html
=
node
.
inner_html
def
validate
needs
:project
unless
skip_project_check?
end
return
unless
link
.
force_encoding
(
'UTF-8'
).
valid_encoding?
# Iterates over all <a> and text() nodes in a document.
#
# Nodes are skipped whenever their ancestor is one of the nodes returned
# by `ignore_ancestor_query`. Link tags are not processed if they have a
# "gfm" class or the "href" attribute is empty.
def
each_node
return
to_enum
(
__method__
)
unless
block_given?
doc
.
xpath
(
query
).
each
do
|
node
|
yield
node
end
end
yield
link
,
inner_html
# Returns an Array containing all HTML nodes.
end
def
nodes
@nodes
||=
each_node
.
to_a
end
def
unescape_link
(
href
)
# Yields the link's URL and inner HTML whenever the node is a valid <a> tag.
CGI
.
unescape
(
href
)
def
yield_valid_link
(
node
)
end
link
=
unescape_link
(
node
.
attr
(
'href'
).
to_s
)
inner_html
=
node
.
inner_html
def
replace_text_when_pattern_matches
(
node
,
index
,
pattern
)
return
unless
link
.
force_encoding
(
'UTF-8'
).
valid_encoding?
return
unless
node
.
text
=~
pattern
content
=
node
.
to
_html
yield
link
,
inner
_html
html
=
yield
content
end
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
content
def
unescape_link
(
href
)
end
CGI
.
unescape
(
href
)
end
def
replace_link_node_with_text
(
node
,
index
)
def
replace_text_when_pattern_matches
(
node
,
index
,
pattern
)
html
=
yield
return
unless
node
.
text
=~
pattern
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
node
.
text
content
=
node
.
to_html
end
html
=
yield
content
def
replace_link_node_with_href
(
node
,
index
,
link
)
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
content
html
=
yiel
d
en
d
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
link
def
replace_link_node_with_text
(
node
,
index
)
en
d
html
=
yiel
d
def
text_node?
(
node
)
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
node
.
text
node
.
is_a?
(
Nokogiri
::
XML
::
Text
)
end
end
def
element_node?
(
node
)
def
replace_link_node_with_href
(
node
,
index
,
link
)
node
.
is_a?
(
Nokogiri
::
XML
::
Element
)
html
=
yield
end
private
replace_text_with_html
(
node
,
index
,
html
)
unless
html
==
link
end
def
query
def
text_node?
(
node
)
@query
||=
%Q{descendant-or-self::text()[not(
#{
ignore_ancestor_query
}
)]
node
.
is_a?
(
Nokogiri
::
XML
::
Text
)
| descendant-or-self::a[
end
not(contains(concat(" ", @class, " "), " gfm ")) and not(@href = "")
]}
end
def
replace_text_with_html
(
node
,
index
,
html
)
def
element_node?
(
node
)
replace_and_update_new_nodes
(
node
,
index
,
html
)
node
.
is_a?
(
Nokogiri
::
XML
::
Element
)
end
end
def
replace_and_update_new_nodes
(
node
,
index
,
html
)
private
previous_node
=
node
.
previous
next_node
=
node
.
next
parent_node
=
node
.
parent
# Unfortunately node.replace(html) returns re-parented nodes, not the actual replaced nodes in the doc
# We need to find the actual nodes in the doc that were replaced
node
.
replace
(
html
)
@new_nodes
[
index
]
=
[]
# We replaced node with new nodes, so we find first new node. If previous_node is nil, we take first parent child
def
query
new_node
=
previous_node
?
previous_node
.
next
:
parent_node
&
.
children
&
.
first
@query
||=
%Q{descendant-or-self::text()[not(
#{
ignore_ancestor_query
}
)]
| descendant-or-self::a[
not(contains(concat(" ", @class, " "), " gfm ")) and not(@href = "")
]}
end
# We iterate from first to last replaced node and store replaced nodes in @new_nodes
def
replace_text_with_html
(
node
,
index
,
html
)
while
new_node
&&
new_node
!=
next_node
replace_and_update_new_nodes
(
node
,
index
,
html
)
@new_nodes
[
index
]
<<
new_node
.
xpath
(
query
)
new_node
=
new_node
.
next
end
end
@new_nodes
[
index
].
flatten!
def
replace_and_update_new_nodes
(
node
,
index
,
html
)
end
previous_node
=
node
.
previous
next_node
=
node
.
next
parent_node
=
node
.
parent
# Unfortunately node.replace(html) returns re-parented nodes, not the actual replaced nodes in the doc
# We need to find the actual nodes in the doc that were replaced
node
.
replace
(
html
)
@new_nodes
[
index
]
=
[]
# We replaced node with new nodes, so we find first new node. If previous_node is nil, we take first parent child
new_node
=
previous_node
?
previous_node
.
next
:
parent_node
&
.
children
&
.
first
# We iterate from first to last replaced node and store replaced nodes in @new_nodes
while
new_node
&&
new_node
!=
next_node
@new_nodes
[
index
]
<<
new_node
.
xpath
(
query
)
new_node
=
new_node
.
next
end
@new_nodes
[
index
].
flatten!
end
def
only_path?
def
only_path?
context
[
:only_path
]
context
[
:only_path
]
end
end
def
with_update_nodes
def
with_update_nodes
@new_nodes
=
{}
@new_nodes
=
{}
yield
.
tap
{
update_nodes!
}
yield
.
tap
{
update_nodes!
}
end
end
# Once Filter completes replacing nodes, we update nodes with @new_nodes
# Once Filter completes replacing nodes, we update nodes with @new_nodes
def
update_nodes!
def
update_nodes!
@new_nodes
.
sort_by
{
|
index
,
_new_nodes
|
-
index
}.
each
do
|
index
,
new_nodes
|
@new_nodes
.
sort_by
{
|
index
,
_new_nodes
|
-
index
}.
each
do
|
index
,
new_nodes
|
nodes
[
index
,
1
]
=
new_nodes
nodes
[
index
,
1
]
=
new_nodes
end
result
[
:reference_filter_nodes
]
=
nodes
end
end
result
[
:reference_filter_nodes
]
=
nodes
end
end
end
end
end
end
...
...
lib/banzai/filter/references/snippet_reference_filter.rb
View file @
7ecc247a
...
@@ -2,27 +2,29 @@
...
@@ -2,27 +2,29 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces snippet references with links. References to
module
References
# snippets that do not exist are ignored.
# HTML filter that replaces snippet references with links. References to
#
# snippets that do not exist are ignored.
# This filter supports cross-project references.
#
class
SnippetReferenceFilter
<
AbstractReferenceFilter
# This filter supports cross-project references.
self
.
reference_type
=
:snippet
class
SnippetReferenceFilter
<
AbstractReferenceFilter
self
.
reference_type
=
:snippet
def
self
.
object_class
def
self
.
object_class
Snippet
Snippet
end
end
def
find_object
(
project
,
id
)
def
find_object
(
project
,
id
)
return
unless
project
.
is_a?
(
Project
)
return
unless
project
.
is_a?
(
Project
)
project
.
snippets
.
find_by
(
id:
id
)
project
.
snippets
.
find_by
(
id:
id
)
end
end
def
url_for_object
(
snippet
,
project
)
def
url_for_object
(
snippet
,
project
)
h
=
Gitlab
::
Routing
.
url_helpers
h
=
Gitlab
::
Routing
.
url_helpers
h
.
project_snippet_url
(
project
,
snippet
,
h
.
project_snippet_url
(
project
,
snippet
,
only_path:
context
[
:only_path
])
only_path:
context
[
:only_path
])
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/user_reference_filter.rb
View file @
7ecc247a
...
@@ -2,178 +2,180 @@
...
@@ -2,178 +2,180 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# HTML filter that replaces user or group references with links.
module
References
#
# HTML filter that replaces user or group references with links.
# A special `@all` reference is also supported.
class
UserReferenceFilter
<
ReferenceFilter
self
.
reference_type
=
:user
# Public: Find `@user` user references in text
#
# UserReferenceFilter.references_in(text) do |match, username|
# "<a href=...>@#{user}</a>"
# end
#
# text - String text to search.
#
# Yields the String match, and the String user name.
#
#
# Returns a String replaced with the return of the block.
# A special `@all` reference is also supported.
def
self
.
references_in
(
text
)
class
UserReferenceFilter
<
ReferenceFilter
text
.
gsub
(
User
.
reference_pattern
)
do
|
match
|
self
.
reference_type
=
:user
yield
match
,
$~
[
:user
]
# Public: Find `@user` user references in text
#
# UserReferenceFilter.references_in(text) do |match, username|
# "<a href=...>@#{user}</a>"
# end
#
# text - String text to search.
#
# Yields the String match, and the String user name.
#
# Returns a String replaced with the return of the block.
def
self
.
references_in
(
text
)
text
.
gsub
(
User
.
reference_pattern
)
do
|
match
|
yield
match
,
$~
[
:user
]
end
end
end
end
def
call
def
call
return
doc
if
project
.
nil?
&&
group
.
nil?
&&
!
skip_project_check?
return
doc
if
project
.
nil?
&&
group
.
nil?
&&
!
skip_project_check?
ref_pattern
=
User
.
reference_pattern
ref_pattern
=
User
.
reference_pattern
ref_pattern_start
=
/\A
#{
ref_pattern
}
\z/
ref_pattern_start
=
/\A
#{
ref_pattern
}
\z/
nodes
.
each_with_index
do
|
node
,
index
|
nodes
.
each_with_index
do
|
node
,
index
|
if
text_node?
(
node
)
if
text_node?
(
node
)
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
replace_text_when_pattern_matches
(
node
,
index
,
ref_pattern
)
do
|
content
|
user_link_filter
(
content
)
user_link_filter
(
content
)
end
end
elsif
element_node?
(
node
)
elsif
element_node?
(
node
)
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
yield_valid_link
(
node
)
do
|
link
,
inner_html
|
if
link
=~
ref_pattern_start
if
link
=~
ref_pattern_start
replace_link_node_with_href
(
node
,
index
,
link
)
do
replace_link_node_with_href
(
node
,
index
,
link
)
do
user_link_filter
(
link
,
link_content:
inner_html
)
user_link_filter
(
link
,
link_content:
inner_html
)
end
end
end
end
end
end
end
end
end
end
doc
doc
end
end
# Replace `@user` user references in text with links to the referenced
# Replace `@user` user references in text with links to the referenced
# user's profile page.
# user's profile page.
#
#
# text - String text to replace references in.
# text - String text to replace references in.
# link_content - Original content of the link being replaced.
# link_content - Original content of the link being replaced.
#
#
# Returns a String with `@user` references replaced with links. All links
# Returns a String with `@user` references replaced with links. All links
# have `gfm` and `gfm-project_member` class names attached for styling.
# have `gfm` and `gfm-project_member` class names attached for styling.
def
user_link_filter
(
text
,
link_content:
nil
)
def
user_link_filter
(
text
,
link_content:
nil
)
self
.
class
.
references_in
(
text
)
do
|
match
,
username
|
self
.
class
.
references_in
(
text
)
do
|
match
,
username
|
if
username
==
'all'
&&
!
skip_project_check?
if
username
==
'all'
&&
!
skip_project_check?
link_to_all
(
link_content:
link_content
)
link_to_all
(
link_content:
link_content
)
else
else
cached_call
(
:banzai_url_for_object
,
match
,
path:
[
User
,
username
.
downcase
])
do
cached_call
(
:banzai_url_for_object
,
match
,
path:
[
User
,
username
.
downcase
])
do
if
namespace
=
namespaces
[
username
.
downcase
]
if
namespace
=
namespaces
[
username
.
downcase
]
link_to_namespace
(
namespace
,
link_content:
link_content
)
||
match
link_to_namespace
(
namespace
,
link_content:
link_content
)
||
match
else
else
match
match
end
end
end
end
end
end
end
end
end
end
# Returns a Hash containing all Namespace objects for the username
# Returns a Hash containing all Namespace objects for the username
# references in the current document.
# references in the current document.
#
#
# The keys of this Hash are the namespace paths, the values the
# The keys of this Hash are the namespace paths, the values the
# corresponding Namespace objects.
# corresponding Namespace objects.
def
namespaces
def
namespaces
@namespaces
||=
Namespace
.
eager_load
(
:owner
,
:route
)
@namespaces
||=
Namespace
.
eager_load
(
:owner
,
:route
)
.
where_full_path_in
(
usernames
)
.
where_full_path_in
(
usernames
)
.
index_by
(
&
:full_path
)
.
index_by
(
&
:full_path
)
.
transform_keys
(
&
:downcase
)
.
transform_keys
(
&
:downcase
)
end
end
# Returns all usernames referenced in the current document.
# Returns all usernames referenced in the current document.
def
usernames
def
usernames
refs
=
Set
.
new
refs
=
Set
.
new
nodes
.
each
do
|
node
|
nodes
.
each
do
|
node
|
node
.
to_html
.
scan
(
User
.
reference_pattern
)
do
node
.
to_html
.
scan
(
User
.
reference_pattern
)
do
refs
<<
$~
[
:user
]
refs
<<
$~
[
:user
]
end
end
end
end
refs
.
to_a
refs
.
to_a
end
end
private
private
def
urls
def
urls
Gitlab
::
Routing
.
url_helpers
Gitlab
::
Routing
.
url_helpers
end
end
def
link_class
def
link_class
[
reference_class
(
:project_member
,
tooltip:
false
),
"js-user-link"
].
join
(
" "
)
[
reference_class
(
:project_member
,
tooltip:
false
),
"js-user-link"
].
join
(
" "
)
end
end
def
link_to_all
(
link_content:
nil
)
def
link_to_all
(
link_content:
nil
)
author
=
context
[
:author
]
author
=
context
[
:author
]
if
author
&&
!
team_member?
(
author
)
if
author
&&
!
team_member?
(
author
)
link_content
link_content
else
else
parent_url
(
link_content
,
author
)
parent_url
(
link_content
,
author
)
end
end
end
end
def
link_to_namespace
(
namespace
,
link_content:
nil
)
def
link_to_namespace
(
namespace
,
link_content:
nil
)
if
namespace
.
is_a?
(
Group
)
if
namespace
.
is_a?
(
Group
)
link_to_group
(
namespace
.
full_path
,
namespace
,
link_content:
link_content
)
link_to_group
(
namespace
.
full_path
,
namespace
,
link_content:
link_content
)
else
else
link_to_user
(
namespace
.
path
,
namespace
,
link_content:
link_content
)
link_to_user
(
namespace
.
path
,
namespace
,
link_content:
link_content
)
end
end
end
end
def
link_to_group
(
group
,
namespace
,
link_content:
nil
)
url
=
urls
.
group_url
(
group
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
group:
namespace
.
id
)
content
=
link_content
||
Group
.
reference_prefix
+
group
link_tag
(
url
,
data
,
content
,
namespace
.
full_name
)
def
link_to_group
(
group
,
namespace
,
link_content:
nil
)
end
url
=
urls
.
group_url
(
group
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
group:
namespace
.
id
)
content
=
link_content
||
Group
.
reference_prefix
+
group
def
link_to_user
(
user
,
namespace
,
link_content:
nil
)
link_tag
(
url
,
data
,
content
,
namespace
.
full_name
)
url
=
urls
.
user_url
(
user
,
only_path:
context
[
:only_path
])
end
data
=
data_attribute
(
user:
namespace
.
owner_id
)
content
=
link_content
||
User
.
reference_prefix
+
user
link_tag
(
url
,
data
,
content
,
namespace
.
owner_name
)
def
link_to_user
(
user
,
namespace
,
link_content:
nil
)
end
url
=
urls
.
user_url
(
user
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
user:
namespace
.
owner_id
)
content
=
link_content
||
User
.
reference_prefix
+
user
def
link_tag
(
url
,
data
,
link_content
,
title
)
link_tag
(
url
,
data
,
content
,
namespace
.
owner_name
)
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
end
end
def
parent
def
link_tag
(
url
,
data
,
link_content
,
title
)
context
[
:project
]
||
context
[
:group
]
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
end
end
def
parent_group?
def
parent
parent
.
is_a?
(
Group
)
context
[
:project
]
||
context
[
:group
]
end
end
def
team_member?
(
user
)
def
parent_group?
if
parent_group?
parent
.
is_a?
(
Group
)
parent
.
member?
(
user
)
else
parent
.
team
.
member?
(
user
)
end
end
end
def
parent_url
(
link_content
,
author
)
def
team_member?
(
user
)
if
parent_group?
if
parent_group?
url
=
urls
.
group_url
(
parent
,
only_path:
context
[
:only_path
])
parent
.
member?
(
user
)
data
=
data_attribute
(
group:
group
.
id
,
author:
author
.
try
(
:id
))
else
else
parent
.
team
.
member?
(
user
)
url
=
urls
.
project_url
(
parent
,
only_path:
context
[
:only_path
])
end
data
=
data_attribute
(
project:
project
.
id
,
author:
author
.
try
(
:id
))
end
end
content
=
link_content
||
User
.
reference_prefix
+
'all'
def
parent_url
(
link_content
,
author
)
link_tag
(
url
,
data
,
content
,
'All Project and Group Members'
)
if
parent_group?
url
=
urls
.
group_url
(
parent
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
group:
group
.
id
,
author:
author
.
try
(
:id
))
else
url
=
urls
.
project_url
(
parent
,
only_path:
context
[
:only_path
])
data
=
data_attribute
(
project:
project
.
id
,
author:
author
.
try
(
:id
))
end
content
=
link_content
||
User
.
reference_prefix
+
'all'
link_tag
(
url
,
data
,
content
,
'All Project and Group Members'
)
end
end
end
end
end
end
end
...
...
lib/banzai/filter/references/vulnerability_reference_filter.rb
View file @
7ecc247a
...
@@ -2,21 +2,23 @@
...
@@ -2,21 +2,23 @@
module
Banzai
module
Banzai
module
Filter
module
Filter
# The actual filter is implemented in the EE mixin
module
References
class
VulnerabilityReferenceFilter
<
IssuableReferenceFilter
# The actual filter is implemented in the EE mixin
self
.
reference_type
=
:vulnerability
class
VulnerabilityReferenceFilter
<
IssuableReferenceFilter
self
.
reference_type
=
:vulnerability
def
self
.
object_class
def
self
.
object_class
Vulnerability
Vulnerability
end
end
private
private
def
project
def
project
context
[
:project
]
context
[
:project
]
end
end
end
end
end
end
end
end
end
Banzai
::
Filter
::
VulnerabilityReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter
::VulnerabilityReferenceFilter'
)
Banzai
::
Filter
::
References
::
VulnerabilityReferenceFilter
.
prepend_if_ee
(
'EE::Banzai::Filter::References
::VulnerabilityReferenceFilter'
)
lib/banzai/pipeline/gfm_pipeline.rb
View file @
7ecc247a
...
@@ -51,19 +51,19 @@ module Banzai
...
@@ -51,19 +51,19 @@ module Banzai
def
self
.
reference_filters
def
self
.
reference_filters
[
[
Filter
::
UserReferenceFilter
,
Filter
::
References
::
UserReferenceFilter
,
Filter
::
ProjectReferenceFilter
,
Filter
::
References
::
ProjectReferenceFilter
,
Filter
::
DesignReferenceFilter
,
Filter
::
References
::
DesignReferenceFilter
,
Filter
::
IssueReferenceFilter
,
Filter
::
References
::
IssueReferenceFilter
,
Filter
::
ExternalIssueReferenceFilter
,
Filter
::
References
::
ExternalIssueReferenceFilter
,
Filter
::
MergeRequestReferenceFilter
,
Filter
::
References
::
MergeRequestReferenceFilter
,
Filter
::
SnippetReferenceFilter
,
Filter
::
References
::
SnippetReferenceFilter
,
Filter
::
CommitRangeReferenceFilter
,
Filter
::
References
::
CommitRangeReferenceFilter
,
Filter
::
CommitReferenceFilter
,
Filter
::
References
::
CommitReferenceFilter
,
Filter
::
LabelReferenceFilter
,
Filter
::
References
::
LabelReferenceFilter
,
Filter
::
MilestoneReferenceFilter
,
Filter
::
References
::
MilestoneReferenceFilter
,
Filter
::
AlertReferenceFilter
,
Filter
::
References
::
AlertReferenceFilter
,
Filter
::
FeatureFlagReferenceFilter
Filter
::
References
::
FeatureFlagReferenceFilter
]
]
end
end
...
...
lib/banzai/pipeline/label_pipeline.rb
View file @
7ecc247a
...
@@ -6,7 +6,7 @@ module Banzai
...
@@ -6,7 +6,7 @@ module Banzai
def
self
.
filters
def
self
.
filters
@filters
||=
FilterArray
[
@filters
||=
FilterArray
[
Filter
::
SanitizationFilter
,
Filter
::
SanitizationFilter
,
Filter
::
LabelReferenceFilter
Filter
::
References
::
LabelReferenceFilter
]
]
end
end
end
end
...
...
lib/banzai/pipeline/single_line_pipeline.rb
View file @
7ecc247a
...
@@ -17,15 +17,15 @@ module Banzai
...
@@ -17,15 +17,15 @@ module Banzai
def
self
.
reference_filters
def
self
.
reference_filters
[
[
Filter
::
UserReferenceFilter
,
Filter
::
References
::
UserReferenceFilter
,
Filter
::
IssueReferenceFilter
,
Filter
::
References
::
IssueReferenceFilter
,
Filter
::
ExternalIssueReferenceFilter
,
Filter
::
References
::
ExternalIssueReferenceFilter
,
Filter
::
MergeRequestReferenceFilter
,
Filter
::
References
::
MergeRequestReferenceFilter
,
Filter
::
SnippetReferenceFilter
,
Filter
::
References
::
SnippetReferenceFilter
,
Filter
::
CommitRangeReferenceFilter
,
Filter
::
References
::
CommitRangeReferenceFilter
,
Filter
::
CommitReferenceFilter
,
Filter
::
References
::
CommitReferenceFilter
,
Filter
::
AlertReferenceFilter
,
Filter
::
References
::
AlertReferenceFilter
,
Filter
::
FeatureFlagReferenceFilter
Filter
::
References
::
FeatureFlagReferenceFilter
]
]
end
end
...
...
spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
AbstractReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
AbstractReferenceFilter
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:doc
)
{
Nokogiri
::
HTML
.
fragment
(
''
)
}
let
(
:doc
)
{
Nokogiri
::
HTML
.
fragment
(
''
)
}
...
...
spec/lib/banzai/filter/references/alert_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
AlertReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
AlertReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let_it_be
(
:project
)
{
create
(
:project
,
:public
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:public
)
}
...
...
spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
CommitRangeReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
CommitRangeReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
...
...
spec/lib/banzai/filter/references/commit_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
CommitReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
CommitReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
:repository
)
}
...
...
spec/lib/banzai/filter/references/design_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
DesignReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
DesignReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
include
DesignManagementTestHelpers
include
DesignManagementTestHelpers
...
...
spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
ExternalIssueReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
ExternalIssueReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let_it_be_with_refind
(
:project
)
{
create
(
:project
)
}
let_it_be_with_refind
(
:project
)
{
create
(
:project
)
}
...
...
spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
FeatureFlagReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
FeatureFlagReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let_it_be
(
:project
)
{
create
(
:project
,
:public
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:public
)
}
...
...
spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
IssueReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
IssueReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
include
DesignManagementTestHelpers
include
DesignManagementTestHelpers
...
...
spec/lib/banzai/filter/references/label_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
require
'spec_helper'
require
'spec_helper'
require
'html/pipeline'
require
'html/pipeline'
RSpec
.
describe
Banzai
::
Filter
::
LabelReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
LabelReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
,
name:
'sample-project'
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
name:
'sample-project'
)
}
...
...
spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
MergeRequestReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
MergeRequestReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
...
...
spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
MilestoneReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
MilestoneReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let_it_be
(
:parent_group
)
{
create
(
:group
,
:public
)
}
let_it_be
(
:parent_group
)
{
create
(
:group
,
:public
)
}
...
...
spec/lib/banzai/filter/references/project_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
ProjectReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
ProjectReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
def
invalidate_reference
(
reference
)
def
invalidate_reference
(
reference
)
...
...
spec/lib/banzai/filter/references/reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
ReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
Reference
s
::
Reference
Filter
do
let
(
:project
)
{
build_stubbed
(
:project
)
}
let
(
:project
)
{
build_stubbed
(
:project
)
}
describe
'#each_node'
do
describe
'#each_node'
do
...
...
spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
SnippetReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
SnippetReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
...
...
spec/lib/banzai/filter/references/user_reference_filter_spec.rb
View file @
7ecc247a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Banzai
::
Filter
::
UserReferenceFilter
do
RSpec
.
describe
Banzai
::
Filter
::
References
::
UserReferenceFilter
do
include
FilterSpecHelper
include
FilterSpecHelper
def
get_reference
(
user
)
def
get_reference
(
user
)
...
...
spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
View file @
7ecc247a
...
@@ -25,7 +25,7 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do
...
@@ -25,7 +25,7 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do
issue
=
create
(
:issue
,
project:
project
)
issue
=
create
(
:issue
,
project:
project
)
markdown
=
"text
#{
issue
.
to_reference
(
project
,
full:
true
)
}
"
markdown
=
"text
#{
issue
.
to_reference
(
project
,
full:
true
)
}
"
expect_any_instance_of
(
Banzai
::
Filter
::
ReferenceFilter
).
to
receive
(
:each_node
).
once
expect_any_instance_of
(
Banzai
::
Filter
::
Reference
s
::
Reference
Filter
).
to
receive
(
:each_node
).
once
described_class
.
call
(
markdown
,
project:
project
)
described_class
.
call
(
markdown
,
project:
project
)
end
end
...
...
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