Skip to content

Commit a68c27d

Browse files
committed
[HTML] Highlight JavaScript escape sequence in string literal.
1 parent 2c69a05 commit a68c27d

1 file changed

Lines changed: 47 additions & 18 deletions

File tree

‎scintilla/lexers/LexHTML.cxx‎

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,30 @@ constexpr bool stateTerminateScript(int state) noexcept {
157157
return !isStringState(state) && !(state >= js_style(SCE_JS_COMMENTBLOCK) && state <= js_style(SCE_JS_TASKMARKER));
158158
}
159159

160+
struct EscapeSequence {
161+
int outerState = SCE_H_DEFAULT;
162+
int digitsLeft = 0;
163+
164+
// highlight any character as escape sequence.
165+
void resetEscapeState(int state, int chNext) noexcept {
166+
outerState = state;
167+
digitsLeft = 1;
168+
if (chNext == 'x') {
169+
digitsLeft = 3;
170+
} else if (chNext == 'u') {
171+
digitsLeft = 5;
172+
}
173+
}
174+
bool atEscapeEnd(int ch) noexcept {
175+
--digitsLeft;
176+
return digitsLeft <= 0 || !IsHexDigit(ch);
177+
}
178+
};
179+
160180
struct HtmlLexer {
161181
int chBefore = 0;
162182
KeywordType kwType = KeywordType::None;
183+
EscapeSequence escSeq;
163184
};
164185

165186
SCI_noinline
@@ -1017,16 +1038,17 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
10171038
state = js_style(SCE_JS_DEFAULT);
10181039
}
10191040
break;
1020-
case js_style(SCE_JS_IDENTIFIER):
10211041
case js_style(SCE_JS_NUMBER):
1022-
if (!(IsJsIdentifierChar(ch) || (state == js_style(SCE_JS_NUMBER) && IsNumberContinueEx(chPrev, ch, chNext)))) {
1023-
if (state == js_style(SCE_JS_NUMBER)) {
1024-
styler.ColorTo(i, state);
1025-
state = js_style(SCE_JS_DEFAULT);
1026-
} else {
1027-
state = js_style(SCE_JS_DEFAULT);
1028-
stylePrevNonWhite = classifyWordHTJS(i, ch, chNext, lexer, keywordLists, styler);
1029-
}
1042+
case SCE_HB_NUMBER:
1043+
if (!(IsIdentifierChar(ch) || IsNumberContinueEx(chPrev, ch, chNext))) {
1044+
styler.ColorTo(i, state);
1045+
state = lexer.escSeq.outerState;
1046+
}
1047+
break;
1048+
case js_style(SCE_JS_IDENTIFIER):
1049+
if (!IsJsIdentifierChar(ch)) {
1050+
state = js_style(SCE_JS_DEFAULT);
1051+
stylePrevNonWhite = classifyWordHTJS(i, ch, chNext, lexer, keywordLists, styler);
10301052
}
10311053
break;
10321054
case js_style(SCE_JS_COMMENTBLOCK):
@@ -1048,7 +1070,10 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
10481070
case js_style(SCE_JS_STRING_SQ):
10491071
case js_style(SCE_JS_TEMPLATELITERAL):
10501072
if (ch == '\\') {
1051-
if (IsAGraphic(chNext)) {
1073+
if (chNext >= ' ') {
1074+
styler.ColorTo(i, state);
1075+
lexer.escSeq.resetEscapeState(state, chNext);
1076+
state = js_style(SCE_JS_ESCAPECHAR);
10521077
i++;
10531078
}
10541079
} else if (ch == ((state == js_style(SCE_JS_STRING_DQ)) ? '\"' : ((state == js_style(SCE_JS_STRING_SQ)) ? '\'' : '`'))) {
@@ -1072,6 +1097,14 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
10721097
state = js_style(SCE_JS_DEFAULT);
10731098
}
10741099
break;
1100+
case js_style(SCE_JS_ESCAPECHAR):
1101+
if (lexer.escSeq.atEscapeEnd(ch)) {
1102+
styler.ColorTo(i, state);
1103+
state = lexer.escSeq.outerState;
1104+
i -= 1;
1105+
continue;
1106+
}
1107+
break;
10751108
case js_style(SCE_JS_REGEX):
10761109
if (ch == '\r' || ch == '\n' || (ch == '/' && !insideRegexCharacterClass)) {
10771110
if (ch == '/') {
@@ -1103,14 +1136,8 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
11031136
}
11041137
break;
11051138
case SCE_HB_IDENTIFIER:
1106-
case SCE_HB_NUMBER:
1107-
if (!(IsIdentifierCharEx(ch) || (state == SCE_HB_NUMBER && IsNumberContinue(chPrev, ch, chNext)))) {
1108-
if (state == SCE_HB_NUMBER) {
1109-
styler.ColorTo(i, state);
1110-
state = SCE_HB_DEFAULT;
1111-
} else {
1112-
state = classifyWordHTVB(i, keywordLists, styler);
1113-
}
1139+
if (!IsIdentifierCharEx(ch)) {
1140+
state = classifyWordHTVB(i, keywordLists, styler);
11141141
}
11151142
break;
11161143
case SCE_HB_STRING:
@@ -1147,6 +1174,7 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
11471174
} else if (ch == '`') {
11481175
state = js_style(SCE_JS_TEMPLATELITERAL);
11491176
} else if (IsNumberStart(ch, chNext)) {
1177+
lexer.escSeq.outerState = js_style(SCE_JS_DEFAULT);
11501178
state = js_style(SCE_JS_NUMBER);
11511179
} else if (IsJsIdentifierStart(ch)) {
11521180
lexer.chBefore = chPrevNonWhite;
@@ -1183,6 +1211,7 @@ void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int init
11831211
} else if (ch == '\'') {
11841212
state = SCE_HB_COMMENTLINE;
11851213
} else if (IsNumberStart(ch, chNext)) {
1214+
lexer.escSeq.outerState = SCE_HB_DEFAULT;
11861215
state = SCE_HB_NUMBER;
11871216
} else if (IsIdentifierStartEx(ch)) {
11881217
state = SCE_HB_IDENTIFIER;

0 commit comments

Comments
 (0)