| '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); |
| }; |
| }); |
| }; |