gitlab-org--gitlab-foss/app/assets/javascripts/editor/editor_markdown_ext.js

96 lines
3.4 KiB
JavaScript

export default {
getSelectedText(selection = this.getSelection()) {
const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
const valArray = this.getValue().split('\n');
let text = '';
if (startLineNumber === endLineNumber) {
text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
} else {
const startLineText = valArray[startLineNumber - 1].slice(startColumn - 1);
const endLineText = valArray[endLineNumber - 1].slice(0, endColumn - 1);
for (let i = startLineNumber, k = endLineNumber - 1; i < k; i += 1) {
text += `${valArray[i]}`;
if (i !== k - 1) text += `\n`;
}
text = text
? [startLineText, text, endLineText].join('\n')
: [startLineText, endLineText].join('\n');
}
return text;
},
replaceSelectedText(text, select = undefined) {
const forceMoveMarkers = !select;
this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
},
moveCursor(dx = 0, dy = 0) {
const pos = this.getPosition();
pos.column += dx;
pos.lineNumber += dy;
this.setPosition(pos);
},
/**
* Adjust existing selection to select text within the original selection.
* - If `selectedText` is not supplied, we fetch selected text with
*
* ALGORITHM:
*
* MULTI-LINE SELECTION
* 1. Find line that contains `toSelect` text.
* 2. Using the index of this line and the position of `toSelect` text in it,
* construct:
* * newStartLineNumber
* * newStartColumn
*
* SINGLE-LINE SELECTION
* 1. Use `startLineNumber` from the current selection as `newStartLineNumber`
* 2. Find the position of `toSelect` text in it to get `newStartColumn`
*
* 3. `newEndLineNumber` — Since this method is supposed to be used with
* markdown decorators that are pretty short, the `newEndLineNumber` is
* suggested to be assumed the same as the startLine.
* 4. `newEndColumn` — pretty obvious
* 5. Adjust the start and end positions of the current selection
* 6. Re-set selection on the instance
*
* @param {string} toSelect - New text to select within current selection.
* @param {string} selectedText - Currently selected text. It's just a
* shortcut: If it's not supplied, we fetch selected text from the instance
*/
selectWithinSelection(toSelect, selectedText) {
const currentSelection = this.getSelection();
if (currentSelection.isEmpty() || !toSelect) {
return;
}
const text = selectedText || this.getSelectedText(currentSelection);
let lineShift;
let newStartLineNumber;
let newStartColumn;
const textLines = text.split('\n');
if (textLines.length > 1) {
// Multi-line selection
lineShift = textLines.findIndex(line => line.indexOf(toSelect) !== -1);
newStartLineNumber = currentSelection.startLineNumber + lineShift;
newStartColumn = textLines[lineShift].indexOf(toSelect) + 1;
} else {
// Single-line selection
newStartLineNumber = currentSelection.startLineNumber;
newStartColumn = currentSelection.startColumn + text.indexOf(toSelect);
}
const newEndLineNumber = newStartLineNumber;
const newEndColumn = newStartColumn + toSelect.length;
const newSelection = currentSelection
.setStartPosition(newStartLineNumber, newStartColumn)
.setEndPosition(newEndLineNumber, newEndColumn);
this.setSelection(newSelection);
},
};