summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/jobs/components/log/line.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/jobs/components/log/line.vue')
-rw-r--r--app/assets/javascripts/jobs/components/log/line.vue51
1 files changed, 42 insertions, 9 deletions
diff --git a/app/assets/javascripts/jobs/components/log/line.vue b/app/assets/javascripts/jobs/components/log/line.vue
index e68d5b8eda4..affaddcdee2 100644
--- a/app/assets/javascripts/jobs/components/log/line.vue
+++ b/app/assets/javascripts/jobs/components/log/line.vue
@@ -1,4 +1,6 @@
<script>
+import { linkRegex } from '../../utils';
+
import LineNumber from './line_number.vue';
export default {
@@ -16,15 +18,46 @@ export default {
render(h, { props }) {
const { line, path } = props;
- const chars = line.content.map(content => {
- return h(
- 'span',
- {
- class: ['gl-white-space-pre-wrap', content.style],
- },
- content.text,
- );
- });
+ let chars;
+ if (gon?.features?.ciJobLineLinks) {
+ chars = line.content.map(content => {
+ return h(
+ 'span',
+ {
+ class: ['gl-white-space-pre-wrap', content.style],
+ },
+ // Simple "tokenization": Split text in chunks of text
+ // which alternate between text and urls.
+ content.text.split(linkRegex).map(chunk => {
+ // Return normal string for non-links
+ if (!chunk.match(linkRegex)) {
+ return chunk;
+ }
+ return h(
+ 'a',
+ {
+ attrs: {
+ href: chunk,
+ class: 'gl-reset-color! gl-text-decoration-underline',
+ rel: 'nofollow noopener noreferrer', // eslint-disable-line @gitlab/require-i18n-strings
+ },
+ },
+ chunk,
+ );
+ }),
+ );
+ });
+ } else {
+ chars = line.content.map(content => {
+ return h(
+ 'span',
+ {
+ class: ['gl-white-space-pre-wrap', content.style],
+ },
+ content.text,
+ );
+ });
+ }
return h('div', { class: 'js-line log-line' }, [
h(LineNumber, {