src/parse/state/tag.js/readAttributeValue
function readAttributeValue ( parser ) {
	let quoteMark;

	if ( parser.eat( `'` ) ) quoteMark = `'`;
	if ( parser.eat( `"` ) ) quoteMark = `"`;

	let currentChunk = {
		start: parser.index,
		end: null,
		type: 'Text',
		data: ''
	};

	const done = quoteMark ?
		char => char === quoteMark :
		char => invalidUnquotedAttributeCharacters.test( char );

	const chunks = [];

	while ( parser.index < parser.template.length ) {
		const index = parser.index;

		if ( parser.eat( '{{' ) ) {
			if ( currentChunk.data ) {
				currentChunk.end = index;
				chunks.push( currentChunk );
			}

			const expression = readExpression( parser );
			parser.allowWhitespace();
			if ( !parser.eat( '}}' ) ) {
				parser.error( `Expected }}` );
			}

			chunks.push({
				start: index,
				end: parser.index,
				type: 'MustacheTag',
				expression
			});

			currentChunk = {
				start: parser.index,
				end: null,
				type: 'Text',
				data: ''
			};
		}

		else if ( done( parser.template[ parser.index ] ) ) {
			currentChunk.end = parser.index;
			if ( quoteMark ) parser.index += 1;

			if ( currentChunk.data ) chunks.push( currentChunk );

			chunks.forEach( chunk => {
				if ( chunk.type === 'Text' ) chunk.data = decodeCharacterReferences( chunk.data );
			});

			return chunks;
		}

		else {
			currentChunk.data += parser.template[ parser.index++ ];
		}
	}

	parser.error( `Unexpected end of input` );
}