Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export function getTextRangeChanges(
before: string,
after: string,
): Promise {
const newRanges: TextEdit[] = [];
let lineNumber = 0;
let column = 0;
const parts = diff(before, after);
// Loop over every part, keeping track of:
// 1. The current line no. and column in the `after` string
// 2. Character ranges for all "added" parts in the `after` string
parts.forEach(part => {
const startLineNumber = lineNumber;
const startColumn = column;
if (part[0] === 0 || part[0] === -1) {
// Split the part into lines. Loop through these lines to find
// the line no. and column at the end of this part.
const substring = part[1];
const lines = substring.split("\n");
lines.forEach((line, lineIndex) => {
// The first `line` is actually just a continuation of the last line
if (lineIndex === 0) {
column += line.length;
const onTitleEditorChanged = () => {
if (!titleCollab) {
return
}
const oldTitle = titleCollab.shared.value().join('')
const newTitle = titleEditor.value
const diffs = Diff(oldTitle, newTitle)
let pos = 0
diffs.forEach((d) => {
if (d[0] === 0) { // EQUAL
pos += d[1].length
} else if (d[0] === -1) { // DELETE
const delText = d[1]
for (let i = delText.length - 1; i >= 0; i--) {
try {
titleCollab.shared.removeAt(pos + i)
} catch (err) {
console.error(err)
onStateChanged()
}
}
} else { // INSERT
applyChanges (target, newText) {
const { collaboration } = this.props
const oldText = this.state.value
const diffs = Diff(oldText, newText)
let pos = 0
diffs.forEach((d) => {
if (d[0] === 0) { // EQUAL
pos += d[1].length
} else if (d[0] === -1) { // DELETE
const delText = d[1]
for (let i = delText.length - 1; i >= 0; i--) {
collaboration.shared.removeAt(pos + i)
}
} else { // INSERT
d[1].split('').forEach((c) => {
collaboration.shared.insertAt(pos, d[1])
})
pos += d[1].length
}
})
onRemoteChange (oldText, newText) {
console.log('onValueChanged', oldText, newText)
const textArea = this.refs.collaborativeTextArea
if (textArea.value === newText) {
console.log('value is the same', textArea.value)
return
}
const cursor = {
start: textArea.selectionStart,
end: textArea.selectionEnd
}
const diffs = Diff(oldText, newText)
let pos = 0
diffs.forEach((d) => {
if (d[0] === 0) { // EQUAL
pos += d[1].length
} else if (d[0] === -1) { // DELETE
const delText = d[1]
if (pos < cursor.start) {
cursor.start -= delText.length
}
if (pos < cursor.end) {
cursor.end -= delText.length
}
} else { // INSERT
const insertText = d[1]
if (pos < cursor.start) {
private async applyComposedEdit(original: string, edit: TextEdit): Promise {
// check complex edit
let { range, newText } = edit
let { nvim, ranges } = this
let doc = TextDocument.create('file:///1', '', 0, original)
let edits: TextEdit[] = []
let diffs = fastDiff(original, newText)
let offset = 0
for (let i = 0; i < diffs.length; i++) {
let diff = diffs[i]
let pos = adjustPosition(range.start, doc.positionAt(offset))
if (diff[0] == fastDiff.EQUAL) {
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.DELETE) {
let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length))
if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) {
// change
edits.push({ range: Range.create(pos, end), newText: diffs[i + 1][1] })
i = i + 1
} else {
// delete
edits.push({ range: Range.create(pos, end), newText: '' })
}
private async applyComposedEdit(original: string, edit: TextEdit): Promise {
// check complex edit
let { range, newText } = edit
let { nvim, ranges } = this
let doc = TextDocument.create('file:///1', '', 0, original)
let edits: TextEdit[] = []
let diffs = fastDiff(original, newText)
let offset = 0
for (let i = 0; i < diffs.length; i++) {
let diff = diffs[i]
let pos = adjustPosition(range.start, doc.positionAt(offset))
if (diff[0] == fastDiff.EQUAL) {
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.DELETE) {
let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length))
if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) {
// change
edits.push({ range: Range.create(pos, end), newText: diffs[i + 1][1] })
i = i + 1
} else {
// delete
edits.push({ range: Range.create(pos, end), newText: '' })
}
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.INSERT) {
edits.push({ range: Range.create(pos, pos), newText: diff[1] })
}
}
if (edits.some(edit => edit.newText.indexOf('\n') != -1 || edit.range.start.line != edit.range.end.line)) {
this.cancel()
let diff = diffs[i]
let pos = orig.positionAt(offset)
if (diff[0] == fastDiff.EQUAL) {
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.DELETE) {
let end = orig.positionAt(offset + diff[1].length)
if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) {
let delta = diffs[i + 1][1].split('\n').length - (end.line - pos.line) - 1
if (delta != 0) lineChanges.push({ delta, lnum: pos.line + startLine })
i = i + 1
} else {
let delta = - (end.line - pos.line)
if (delta != 0) lineChanges.push({ delta, lnum: pos.line + startLine })
}
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.INSERT) {
let delta = diff[1].split('\n').length - 1
if (delta != 0) lineChanges.push({ delta, lnum: pos.line + startLine })
}
}
} else {
lineChanges = [{ delta: lineChange, lnum: range.start.line }]
}
let changed = false
// adjust LineNr highlights
for (let item of fileItems) {
for (let range of item.ranges) {
let arr = lineChanges.filter(o => o.lnum < range.lnum - 1)
if (arr.length) {
let total = arr.reduce((p, c) => p + c.delta, 0)
range.lnum = range.lnum + total
changed = true
private async applyComposedEdit(original: string, edit: TextEdit): Promise {
// check complex edit
let { range, newText } = edit
let { nvim, ranges } = this
let doc = TextDocument.create('file:///1', '', 0, original)
let edits: TextEdit[] = []
let diffs = fastDiff(original, newText)
let offset = 0
for (let i = 0; i < diffs.length; i++) {
let diff = diffs[i]
let pos = adjustPosition(range.start, doc.positionAt(offset))
if (diff[0] == fastDiff.EQUAL) {
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.DELETE) {
let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length))
if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) {
// change
edits.push({ range: Range.create(pos, end), newText: diffs[i + 1][1] })
i = i + 1
} else {
// delete
edits.push({ range: Range.create(pos, end), newText: '' })
}
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.INSERT) {
edits.push({ range: Range.create(pos, pos), newText: diff[1] })
}
}
if (edits.some(edit => edit.newText.indexOf('\n') != -1 || edit.range.start.line != edit.range.end.line)) {
this.cancel()
return
}
function diffLine (theme, actual, expected) {
const outcome = fastDiff(actual, expected)
// TODO: Compute when line is mostly unequal (80%? 90%?) and treat it as being
// completely unequal.
const isPartiallyEqual = !(
(outcome.length === 2 && outcome[0][1] === actual && outcome[1][1] === expected) ||
// Discount line ending control pictures, which will be equal even when the
// rest of the line isn't.
(
outcome.length === 3 &&
outcome[2][0] === fastDiff.EQUAL &&
MATCH_CONTROL_PICTURES.test(outcome[2][1]) &&
outcome[0][1] + outcome[2][1] === actual &&
outcome[1][1] + outcome[2][1] === expected
)
)
let stringActual = ''
let stringExpected = ''
const noopWrap = { open: '', close: '' }
const deleteWrap = isPartiallyEqual ? theme.string.diff.delete : noopWrap
const insertWrap = isPartiallyEqual ? theme.string.diff.insert : noopWrap
const equalWrap = isPartiallyEqual ? theme.string.diff.equal : noopWrap
for (const diff of outcome) {
if (diff[0] === fastDiff.DELETE) {
stringActual += formatUtils.wrap(deleteWrap, diff[1])
private async applyComposedEdit(original: string, edit: TextEdit): Promise {
// check complex edit
let { range, newText } = edit
let { nvim, ranges } = this
let doc = TextDocument.create('file:///1', '', 0, original)
let edits: TextEdit[] = []
let diffs = fastDiff(original, newText)
let offset = 0
for (let i = 0; i < diffs.length; i++) {
let diff = diffs[i]
let pos = adjustPosition(range.start, doc.positionAt(offset))
if (diff[0] == fastDiff.EQUAL) {
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.DELETE) {
let end = adjustPosition(range.start, doc.positionAt(offset + diff[1].length))
if (diffs[i + 1] && diffs[i + 1][0] == fastDiff.INSERT) {
// change
edits.push({ range: Range.create(pos, end), newText: diffs[i + 1][1] })
i = i + 1
} else {
// delete
edits.push({ range: Range.create(pos, end), newText: '' })
}
offset = offset + diff[1].length
} else if (diff[0] == fastDiff.INSERT) {
edits.push({ range: Range.create(pos, pos), newText: diff[1] })
}
}