1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
import { TextDocument, Range, Position } from 'vscode-languageserver'
export function isValidLocationForEmmetAbbreviation(
document: TextDocument,
abbreviationRange: Range
): boolean {
const startAngle = '<'
const endAngle = '>'
const escape = '\\'
const question = '?'
let start: Position = { line: 0, character: 0 }
let textToBackTrack = document.getText({
start: {
line: start.line,
character: start.character,
},
end: {
line: abbreviationRange.start.line,
character: abbreviationRange.start.character,
},
})
// Worse case scenario is when cursor is inside a big chunk of text which needs to backtracked
// Backtrack only 500 offsets to ensure we dont waste time doing this
if (textToBackTrack.length > 500) {
textToBackTrack = textToBackTrack.substr(textToBackTrack.length - 500)
}
if (!textToBackTrack.trim()) {
return true
}
let valid = true
let foundSpace = false // If < is found before finding whitespace, then its valid abbreviation. E.g.: <div|
let i = textToBackTrack.length - 1
if (textToBackTrack[i] === startAngle) {
return false
}
while (i >= 0) {
const char = textToBackTrack[i]
i--
if (!foundSpace && /\s/.test(char)) {
foundSpace = true
continue
}
if (char === question && textToBackTrack[i] === startAngle) {
i--
continue
}
// Fix for https://github.com/Microsoft/vscode/issues/55411
// A space is not a valid character right after < in a tag name.
if (/\s/.test(char) && textToBackTrack[i] === startAngle) {
i--
continue
}
if (char !== startAngle && char !== endAngle) {
continue
}
if (i >= 0 && textToBackTrack[i] === escape) {
i--
continue
}
if (char === endAngle) {
if (i >= 0 && textToBackTrack[i] === '=') {
continue // False alarm of cases like =>
} else {
break
}
}
if (char === startAngle) {
valid = !foundSpace
break
}
}
return valid
}
|