Skip to content

Commit f9b1e2d

Browse files
committed
[htmlmixed mode] Support multi-line opening tags for other-language blocks
Closes codemirror#3804
1 parent 3df470a commit f9b1e2d

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

mode/htmlmixed/htmlmixed.js

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,9 @@
4444
return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
4545
}
4646

47-
function getAttrValue(stream, attr) {
48-
var pos = stream.pos, match;
49-
while (pos >= 0 && stream.string.charAt(pos) !== "<") pos--;
50-
if (pos < 0) return pos;
51-
if (match = stream.string.slice(pos, stream.pos).match(getAttrRegexp(attr)))
52-
return match[2];
53-
return "";
47+
function getAttrValue(text, attr) {
48+
var match = text.match(getAttrRegexp(attr))
49+
return match ? match[2] : ""
5450
}
5551

5652
function getTagRegexp(tagName, anchored) {
@@ -66,10 +62,10 @@
6662
}
6763
}
6864

69-
function findMatchingMode(tagInfo, stream) {
65+
function findMatchingMode(tagInfo, tagText) {
7066
for (var i = 0; i < tagInfo.length; i++) {
7167
var spec = tagInfo[i];
72-
if (!spec[0] || spec[1].test(getAttrValue(stream, spec[0]))) return spec[2];
68+
if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
7369
}
7470
}
7571

@@ -89,15 +85,17 @@
8985
tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
9086

9187
function html(stream, state) {
92-
var tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase();
93-
var tagInfo = tagName && tags.hasOwnProperty(tagName) && tags[tagName];
94-
95-
var style = htmlMode.token(stream, state.htmlState), modeSpec;
96-
97-
if (tagInfo && /\btag\b/.test(style) && stream.current() === ">" &&
98-
(modeSpec = findMatchingMode(tagInfo, stream))) {
99-
var mode = CodeMirror.getMode(config, modeSpec);
100-
var endTagA = getTagRegexp(tagName, true), endTag = getTagRegexp(tagName, false);
88+
var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
89+
if (tag && !/[<>\s\/]/.test(stream.current()) &&
90+
(tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
91+
tags.hasOwnProperty(tagName)) {
92+
state.inTag = tagName + " "
93+
} else if (state.inTag && tag && />$/.test(stream.current())) {
94+
var inTag = /^([\S]+) (.*)/.exec(state.inTag)
95+
state.inTag = null
96+
var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
97+
var mode = CodeMirror.getMode(config, modeSpec)
98+
var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
10199
state.token = function (stream, state) {
102100
if (stream.match(endTagA, false)) {
103101
state.token = html;
@@ -108,22 +106,26 @@
108106
};
109107
state.localMode = mode;
110108
state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
109+
} else if (state.inTag) {
110+
state.inTag += stream.current()
111+
if (stream.eol()) state.inTag += " "
111112
}
112113
return style;
113114
};
114115

115116
return {
116117
startState: function () {
117118
var state = htmlMode.startState();
118-
return {token: html, localMode: null, localState: null, htmlState: state};
119+
return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
119120
},
120121

121122
copyState: function (state) {
122123
var local;
123124
if (state.localState) {
124125
local = CodeMirror.copyState(state.localMode, state.localState);
125126
}
126-
return {token: state.token, localMode: state.localMode, localState: local,
127+
return {token: state.token, inTag: state.inTag,
128+
localMode: state.localMode, localState: local,
127129
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
128130
},
129131

0 commit comments

Comments
 (0)