diff --git a/app/assets/stylesheets/page_bundles/xterm.scss b/app/assets/stylesheets/page_bundles/xterm.scss
index de3f2a1177d..96df5789eba 100644
--- a/app/assets/stylesheets/page_bundles/xterm.scss
+++ b/app/assets/stylesheets/page_bundles/xterm.scss
@@ -1452,4 +1452,23 @@
.xterm-fg-255 {
color: $xterm-fg-255;
}
+
+ .section-start + p {
+ cursor: pointer;
+ }
+
+ .section-start {
+ width: 1rem;
+ };
+
+ .section.line {
+ padding-left: 0.5rem;
+ margin-left: 0.5rem;
+ }
+
+ .section.not-used:not(.section-header):not(.open) {
+ display: none;
+ height: 0;
+ min-height: 0;
+ }
}
diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb
index fba0de20ced..b34f8d26f00 100644
--- a/lib/gitlab/ci/ansi2html.rb
+++ b/lib/gitlab/ci/ansi2html.rb
@@ -131,9 +131,9 @@ module Gitlab
def on_109(_) set_bg_color(9, 'l') end
- attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask
+ attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask, :sections, :lineno_in_section
- STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask].freeze
+ STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask, :sections, :lineno_in_section].freeze
def convert(stream, new_state)
reset_state
@@ -153,12 +153,9 @@ module Gitlab
start_offset = @offset
- open_new_tag
-
stream.each_line do |line|
s = StringScanner.new(line)
until s.eos?
-
if s.scan(Gitlab::Regex.build_trace_section_regex)
handle_section(s)
elsif s.scan(/\e([@-_])(.*?)([@-~])/)
@@ -166,11 +163,11 @@ module Gitlab
elsif s.scan(/\e(([@-_])(.*?)?)?$/)
break
elsif s.scan(/)
- @out << '<'
+ write_in_tag '<'
elsif s.scan(/\r?\n/)
- @out << '
'
+ handle_new_line
else
- @out << s.scan(/./m)
+ write_in_tag s.scan(/./m)
end
@offset += s.matched_size
@@ -190,13 +187,102 @@ module Gitlab
)
end
+ def handle_new_line
+ css_classes = []
+
+ if @sections.any?
+ css_classes << "section"
+ css_classes += sections.map { |section| "s_#{section}" }
+ css_classes << "line"
+ end
+
+ write_in_tag %{
}
+ write_raw %{} if css_classes.any?
+ @lineno_in_section += 1
+ open_new_tag
+ end
+
def handle_section(scanner)
action = scanner[1]
timestamp = scanner[2]
section = scanner[3]
line = scanner.matched[0...-5] # strips \r\033[0K
- @out << %{