|
60 | 60 | if (!ranges[i].empty()) return CodeMirror.Pass; |
61 | 61 | var pos = ranges[i].head, tok = cm.getTokenAt(pos); |
62 | 62 | var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; |
63 | | - if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; |
| 63 | + var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state) |
| 64 | + var tagName = tagInfo && tagInfo.name |
| 65 | + if (!tagName) return CodeMirror.Pass |
64 | 66 |
|
65 | 67 | var html = inner.mode.configuration == "html"; |
66 | 68 | var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); |
67 | 69 | var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); |
68 | 70 |
|
69 | | - var tagName = state.tagName; |
70 | 71 | if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); |
71 | 72 | var lowerTagName = tagName.toLowerCase(); |
72 | 73 | // Don't process the '>' at the end of an end-tag or self-closing tag |
73 | 74 | if (!tagName || |
74 | 75 | tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || |
75 | | - tok.type == "tag" && state.type == "closeTag" || |
| 76 | + tok.type == "tag" && tagInfo.close || |
76 | 77 | tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName /> |
77 | 78 | dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || |
78 | | - closingTagExists(cm, tagName, pos, state, true)) |
| 79 | + closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true)) |
79 | 80 | return CodeMirror.Pass; |
80 | 81 |
|
81 | 82 | var emptyTags = typeof opt == "object" && opt.emptyTags; |
|
120 | 121 | // when completing in JS/CSS snippet in htmlmixed mode. Does not |
121 | 122 | // work for other XML embedded languages (there is no general |
122 | 123 | // way to go from a mixed mode to its current XML state). |
123 | | - var replacement; |
124 | | - if (inner.mode.name != "xml") { |
125 | | - if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript") |
126 | | - replacement = head + "script"; |
127 | | - else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css") |
128 | | - replacement = head + "style"; |
129 | | - else |
130 | | - return CodeMirror.Pass; |
| 124 | + var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed" |
| 125 | + if (mixed && inner.mode.name == "javascript") { |
| 126 | + replacement = head + "script"; |
| 127 | + } else if (mixed && inner.mode.name == "css") { |
| 128 | + replacement = head + "style"; |
131 | 129 | } else { |
132 | | - if (!state.context || !state.context.tagName || |
133 | | - closingTagExists(cm, state.context.tagName, pos, state)) |
| 130 | + var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) |
| 131 | + if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos))) |
134 | 132 | return CodeMirror.Pass; |
135 | | - replacement = head + state.context.tagName; |
| 133 | + replacement = head + context[context.length - 1] |
136 | 134 | } |
137 | 135 | if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">"; |
138 | 136 | replacements[i] = replacement; |
|
162 | 160 |
|
163 | 161 | // If xml-fold is loaded, we use its functionality to try and verify |
164 | 162 | // whether a given tag is actually unclosed. |
165 | | - function closingTagExists(cm, tagName, pos, state, newTag) { |
| 163 | + function closingTagExists(cm, context, tagName, pos, newTag) { |
166 | 164 | if (!CodeMirror.scanForClosingTag) return false; |
167 | 165 | var end = Math.min(cm.lastLine() + 1, pos.line + 500); |
168 | 166 | var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end); |
169 | 167 | if (!nextClose || nextClose.tag != tagName) return false; |
170 | | - var cx = state.context; |
171 | 168 | // If the immediate wrapping context contains onCx instances of |
172 | 169 | // the same tag, a closing tag only exists if there are at least |
173 | 170 | // that many closing tags of that type following. |
174 | | - for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx; |
| 171 | + var onCx = newTag ? 1 : 0 |
| 172 | + for (var i = context.length - 1; i >= 0; i--) { |
| 173 | + if (context[i] == tagName) ++onCx |
| 174 | + else break |
| 175 | + } |
175 | 176 | pos = nextClose.to; |
176 | 177 | for (var i = 1; i < onCx; i++) { |
177 | 178 | var next = CodeMirror.scanForClosingTag(cm, pos, null, end); |
|
0 commit comments