(stream, state)
| 321 | |
| 322 | // tokenizer for XML attributes |
| 323 | function tokenAttribute(stream, state) { |
| 324 | var ch = stream.next(); |
| 325 | |
| 326 | if(ch == "/" && stream.eat(">")) { |
| 327 | if(isInXmlAttributeBlock(state)) popStateStack(state); |
| 328 | if(isInXmlBlock(state)) popStateStack(state); |
| 329 | return ret("tag", "tag"); |
| 330 | } |
| 331 | if(ch == ">") { |
| 332 | if(isInXmlAttributeBlock(state)) popStateStack(state); |
| 333 | return ret("tag", "tag"); |
| 334 | } |
| 335 | if(ch == "=") |
| 336 | return ret("", null); |
| 337 | // quoted string |
| 338 | if (ch == '"' || ch == "'") |
| 339 | return chain(stream, state, tokenString(ch, tokenAttribute)); |
| 340 | |
| 341 | if(!isInXmlAttributeBlock(state)) |
| 342 | pushStateStack(state, { type: "attribute", tokenize: tokenAttribute}); |
| 343 | |
| 344 | stream.eat(/[a-zA-Z_:]/); |
| 345 | stream.eatWhile(/[-a-zA-Z0-9_:.]/); |
| 346 | stream.eatSpace(); |
| 347 | |
| 348 | // the case where the attribute has not value and the tag was closed |
| 349 | if(stream.match(">", false) || stream.match("/", false)) { |
| 350 | popStateStack(state); |
| 351 | state.tokenize = tokenBase; |
| 352 | } |
| 353 | |
| 354 | return ret("attribute", "attribute"); |
| 355 | } |
| 356 | |
| 357 | // handle comments, including nested |
| 358 | function tokenXMLComment(stream, state) { |
nothing calls this directly
no test coverage detected