'use strict'; exports.assign = function (tokenizer) { //NOTE: obtain Tokenizer proto this way to avoid module circular references var tokenizerProto = Object.getPrototypeOf(tokenizer); tokenizer.tokenStartLoc = -1; //NOTE: add location info builder method tokenizer._attachLocationInfo = function (token) { token.location = { start: this.tokenStartLoc, end: -1 }; }; //NOTE: patch token creation methods and attach location objects tokenizer._createStartTagToken = function (tagNameFirstCh) { tokenizerProto._createStartTagToken.call(this, tagNameFirstCh); this._attachLocationInfo(this.currentToken); }; tokenizer._createEndTagToken = function (tagNameFirstCh) { tokenizerProto._createEndTagToken.call(this, tagNameFirstCh); this._attachLocationInfo(this.currentToken); }; tokenizer._createCommentToken = function () { tokenizerProto._createCommentToken.call(this); this._attachLocationInfo(this.currentToken); }; tokenizer._createDoctypeToken = function (doctypeNameFirstCh) { tokenizerProto._createDoctypeToken.call(this, doctypeNameFirstCh); this._attachLocationInfo(this.currentToken); }; tokenizer._createCharacterToken = function (type, ch) { tokenizerProto._createCharacterToken.call(this, type, ch); this._attachLocationInfo(this.currentCharacterToken); }; //NOTE: patch token emission methods to determine end location tokenizer._emitCurrentToken = function () { //NOTE: if we have pending character token make it's end location equal to the //current token's start location. if (this.currentCharacterToken) this.currentCharacterToken.location.end = this.currentToken.location.start; this.currentToken.location.end = this.preprocessor.pos + 1; tokenizerProto._emitCurrentToken.call(this); }; tokenizer._emitCurrentCharacterToken = function () { //NOTE: if we have character token and it's location wasn't set in the _emitCurrentToken(), //then set it's location at the current preprocessor position if (this.currentCharacterToken && this.currentCharacterToken.location.end === -1) { //NOTE: we don't need to increment preprocessor position, since character token //emission is always forced by the start of the next character token here. //So, we already have advanced position. this.currentCharacterToken.location.end = this.preprocessor.pos; } tokenizerProto._emitCurrentCharacterToken.call(this); }; //NOTE: patch initial states for each mode to obtain token start position Object.keys(tokenizerProto.MODE) .map(function (modeName) { return tokenizerProto.MODE[modeName]; }) .forEach(function (state) { tokenizer[state] = function (cp) { this.tokenStartLoc = this.preprocessor.pos; tokenizerProto[state].call(this, cp); }; }); };