Skip to content
Snippets Groups Projects
Verified Commit a1327986 authored by Jacques Erasmus's avatar Jacques Erasmus :speech_balloon: Committed by GitLab
Browse files

Merge branch '477336-add-multi-step-numbers' into 'master'

Add multi steps numbers

See merge request !162225



Merged-by: default avatarJacques Erasmus <jerasmus@gitlab.com>
Approved-by: default avatarJacques Erasmus <jerasmus@gitlab.com>
Reviewed-by: default avatarJacques Erasmus <jerasmus@gitlab.com>
Reviewed-by: default avatarChen Charnolevsky <ccharnolevsky@gitlab.com>
Co-authored-by: default avatarChen Charnolevsky <ccharnolevsky@gitlab.com>
parents 823ab847 cd910302
No related branches found
No related tags found
2 merge requests!164749Enable parallel in test-on-omnibus,!162225Add multi steps numbers
Pipeline #1411303582 passed
......@@ -9,16 +9,24 @@
* @param {Object} markLineInfo - highlighting info for the current line
*/
function markLinesWithDiv(content, lineNum, markLineInfo) {
let stepNumberSpan = '';
let stepNumberSpanNone = '';
let wrappedLine = content;
const stepNumberSpan =
lineNum === markLineInfo?.startLine
? `<span class="inline-item-mark">${markLineInfo.index + 1}</span>`
: '';
const stepNumberSpanNone =
lineNum !== markLineInfo?.startLine && markLineInfo
? `<span class="inline-item-mark gl-opacity-0">${markLineInfo.index + 1}</span>`
: '';
// Combines an array of step numbers into a comma-separated string
const stepNumbersArr = markLineInfo?.map((markLine) => markLine.stepNumber);
const stepNumbers = stepNumbersArr?.map(String).join(',') ?? '';
markLineInfo?.forEach((markLine) => {
stepNumberSpan +=
lineNum === markLine.startLine
? `<span id="TEXT-SPAN-MARKER${markLine.stepNumber}" class="inline-item-mark">${markLine.stepNumber}</span>`
: '';
stepNumberSpanNone +=
lineNum !== markLine.startLine
? `<span id="TEXT-SPAN-MARKER${markLine.stepNumber}" class="inline-item-mark gl-opacity-0">${markLine.stepNumber}</span>`
: '';
});
if (markLineInfo) {
const contentStartIndex = content.indexOf(content.trimStart());
......@@ -26,7 +34,7 @@ function markLinesWithDiv(content, lineNum, markLineInfo) {
0,
contentStartIndex,
)}${stepNumberSpanNone}<span id="TEXT-MARKER${
markLineInfo.index + 1
stepNumbers
}-L${lineNum}" class="inline-section-marker">${stepNumberSpan}${content.slice(contentStartIndex)}</span>`;
}
return `<div class="line">${wrappedLine}</div>`;
......
......@@ -112,7 +112,11 @@ export default {
elements.forEach((el) => {
el.classList.remove('selected-inline-section-marker');
});
const element = document.querySelectorAll(`[id^=TEXT-MARKER${this.selectedStepNumber}]`);
// Examples of ID: 'TEXT-MARKER1,2-L8', 'TEXT-MARKER3-L7'
const element = document.querySelectorAll(
`[id^="TEXT-MARKER"][id*="${this.selectedStepNumber}-L"], [id^="TEXT-MARKER"][id*=",${this.selectedStepNumber}-L"], [id^="TEXT-MARKER"][id*="${this.selectedStepNumber},"][id*="-L"]`,
);
if (element) {
element.forEach((el) => el.classList.add('selected-inline-section-marker'));
}
......@@ -121,12 +125,14 @@ export default {
// Highlights the step number in the markdown
const elements = document.querySelectorAll('[id^="TEXT-MARKER"]');
elements.forEach((el) => {
const firstSpan = el.querySelector('span.inline-item-mark');
firstSpan?.classList.remove('selected-inline-item-mark');
const spans = el.querySelectorAll('span.inline-item-mark');
spans.forEach((span) => {
span.classList.remove('selected-inline-item-mark');
});
});
const element = document.querySelector(`[id^=TEXT-MARKER${this.selectedStepNumber}]`);
const element = document.querySelector(`[id^="TEXT-SPAN-MARKER${this.selectedStepNumber}"]`);
if (element) {
element.querySelector('span.inline-item-mark').classList.add('selected-inline-item-mark');
element.classList.add('selected-inline-item-mark');
}
},
markdownRowNumber() {
......@@ -137,7 +143,10 @@ export default {
el.classList.add('unselected-inline-number-mark');
});
const element = document.querySelector(`[id^=NUM-MARKER${this.selectedStepNumber}]`);
// Examples of ID: 'NUM-MARKER1,2-L8', 'NUM-MARKER3-L7'
const element = document.querySelector(
`[id^="NUM-MARKER"][id*="${this.selectedStepNumber}-L"], [id^="NUM-MARKER"][id*=",${this.selectedStepNumber}-L"], [id^="NUM-MARKER"][id*="${this.selectedStepNumber},"][id*="-L"]`,
);
if (element) {
element.classList.add('selected-inline-number-mark');
element.classList.remove('unselected-inline-number-mark');
......
......@@ -81,7 +81,7 @@ export const updateLinesToMarker = (codeBlocks) => {
highlightInfo.forEach((item) => {
const endLine = item.endLine || item.startLine;
for (let k = item.startLine; k <= endLine; k += 1) {
acc[k] = item;
(acc[k] || (acc[k] = [])).push(item);
}
});
return acc;
......
......@@ -28,10 +28,16 @@ export default {
stepNumber: highlight.stepNumber,
};
});
return Array.from({ length: this.endLine - this.startLine + 1 }, (_, i) => ({
lineNumber: this.startLine + i,
stepNumber: linesNumbers.find((line) => line.lineNumber === this.startLine + i)?.stepNumber,
}));
return Array.from({ length: this.endLine - this.startLine + 1 }, (_, i) => {
const currentLineNumber = this.startLine + i;
return {
lineNumber: currentLineNumber,
// Combines the step numbers into a comma-separated string
stepNumbers: linesNumbers
.filter((line) => line.lineNumber === currentLineNumber)
.map((step) => step.stepNumber),
};
});
},
sourceCodeLines() {
const lines = this.content.split('\n');
......@@ -73,7 +79,7 @@ export default {
>
<a
v-for="line in lineNumbers"
:id="`NUM-MARKER${line.stepNumber}-L${line.lineNumber}`"
:id="`NUM-MARKER${line.stepNumbers}-L${line.lineNumber}`"
:key="line.lineNumber"
class="file-line-num hover:gl-no-underline unselected-inline-number-mark"
>
......
......@@ -125,8 +125,8 @@ describe('updateLinesToMarker', () => {
];
const result = updateLinesToMarker(input);
expect(result).toEqual({
1: { startLine: 1, info: 'Line 1' },
3: { startLine: 3, info: 'Line 3' },
1: [{ startLine: 1, info: 'Line 1' }],
3: [{ startLine: 3, info: 'Line 3' }],
});
});
......@@ -138,9 +138,9 @@ describe('updateLinesToMarker', () => {
];
const result = updateLinesToMarker(input);
expect(result).toEqual({
1: { startLine: 1, endLine: 3, info: 'Lines 1-3' },
2: { startLine: 1, endLine: 3, info: 'Lines 1-3' },
3: { startLine: 1, endLine: 3, info: 'Lines 1-3' },
1: [{ startLine: 1, endLine: 3, info: 'Lines 1-3' }],
2: [{ startLine: 1, endLine: 3, info: 'Lines 1-3' }],
3: [{ startLine: 1, endLine: 3, info: 'Lines 1-3' }],
});
});
......@@ -155,9 +155,33 @@ describe('updateLinesToMarker', () => {
];
const result = updateLinesToMarker(input);
expect(result).toEqual({
1: { startLine: 1, endLine: 2, info: 'Block 1' },
2: { startLine: 1, endLine: 2, info: 'Block 1' },
4: { startLine: 4, info: 'Block 2' },
1: [{ startLine: 1, endLine: 2, info: 'Block 1' }],
2: [{ startLine: 1, endLine: 2, info: 'Block 1' }],
4: [{ startLine: 4, info: 'Block 2' }],
});
});
it('should handle overlapping highlights', () => {
const input = [
{
highlightInfo: [
{ startLine: 1, endLine: 3, info: 'Block 1' },
{ startLine: 2, endLine: 4, info: 'Block 2' },
],
},
];
const result = updateLinesToMarker(input);
expect(result).toEqual({
1: [{ startLine: 1, endLine: 3, info: 'Block 1' }],
2: [
{ startLine: 1, endLine: 3, info: 'Block 1' },
{ startLine: 2, endLine: 4, info: 'Block 2' },
],
3: [
{ startLine: 1, endLine: 3, info: 'Block 1' },
{ startLine: 2, endLine: 4, info: 'Block 2' },
],
4: [{ startLine: 2, endLine: 4, info: 'Block 2' }],
});
});
......
......@@ -5,15 +5,23 @@ describe('Highlight.js plugin for mark multi lines', () => {
const inputValue = `<span class="hljs-keyword">FROM</span> alpine:latest<span class="hljs-keyword">COPY</span> . /tmp<span class="hljs-keyword">CMD</span> /tmp/run-app`;
const hljsResultMock = { value: inputValue, language: 'dockerfile' };
const lineToMarkersInfo = {
1: {
index: 1,
startLine: 1,
endLine: 2,
stepNumber: 2,
},
1: [
{
index: 1,
stepNumber: 2,
startLine: 1,
endLine: 2,
},
{
index: 2,
stepNumber: 3,
startLine: 1,
endLine: 1,
},
],
};
const wrappedLine = `<span id="TEXT-MARKER2-L1" class="inline-section-marker"><span class="inline-item-mark">2</span><span class="hljs-keyword">FROM</span> alpine:latest<span class="hljs-keyword">COPY</span> . /tmp<span class="hljs-keyword">CMD</span> /tmp/run-app</span>`;
const wrappedLine = `<span id="TEXT-MARKER2,3-L1" class="inline-section-marker"><span id="TEXT-SPAN-MARKER2" class="inline-item-mark">2</span><span id="TEXT-SPAN-MARKER3" class="inline-item-mark">3</span><span class="hljs-keyword">FROM</span> alpine:latest<span class="hljs-keyword">COPY</span> . /tmp<span class="hljs-keyword">CMD</span> /tmp/run-app</span>`;
const outputValue = `<div class="line">${wrappedLine}</div>`;
markMultipleLines(hljsResultMock, lineToMarkersInfo);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment