1'use strict'; 2 3exports.assign = function (tokenizer) { 4 //NOTE: obtain Tokenizer proto this way to avoid module circular references 5 var tokenizerProto = Object.getPrototypeOf(tokenizer); 6 7 tokenizer.tokenStartLoc = -1; 8 9 //NOTE: add location info builder method 10 tokenizer._attachLocationInfo = function (token) { 11 token.location = { 12 start: this.tokenStartLoc, 13 end: -1 14 }; 15 }; 16 17 //NOTE: patch token creation methods and attach location objects 18 tokenizer._createStartTagToken = function (tagNameFirstCh) { 19 tokenizerProto._createStartTagToken.call(this, tagNameFirstCh); 20 this._attachLocationInfo(this.currentToken); 21 }; 22 23 tokenizer._createEndTagToken = function (tagNameFirstCh) { 24 tokenizerProto._createEndTagToken.call(this, tagNameFirstCh); 25 this._attachLocationInfo(this.currentToken); 26 }; 27 28 tokenizer._createCommentToken = function () { 29 tokenizerProto._createCommentToken.call(this); 30 this._attachLocationInfo(this.currentToken); 31 }; 32 33 tokenizer._createDoctypeToken = function (doctypeNameFirstCh) { 34 tokenizerProto._createDoctypeToken.call(this, doctypeNameFirstCh); 35 this._attachLocationInfo(this.currentToken); 36 }; 37 38 tokenizer._createCharacterToken = function (type, ch) { 39 tokenizerProto._createCharacterToken.call(this, type, ch); 40 this._attachLocationInfo(this.currentCharacterToken); 41 }; 42 43 //NOTE: patch token emission methods to determine end location 44 tokenizer._emitCurrentToken = function () { 45 //NOTE: if we have pending character token make it's end location equal to the 46 //current token's start location. 47 if (this.currentCharacterToken) 48 this.currentCharacterToken.location.end = this.currentToken.location.start; 49 50 this.currentToken.location.end = this.preprocessor.pos + 1; 51 tokenizerProto._emitCurrentToken.call(this); 52 }; 53 54 tokenizer._emitCurrentCharacterToken = function () { 55 //NOTE: if we have character token and it's location wasn't set in the _emitCurrentToken(), 56 //then set it's location at the current preprocessor position 57 if (this.currentCharacterToken && this.currentCharacterToken.location.end === -1) { 58 //NOTE: we don't need to increment preprocessor position, since character token 59 //emission is always forced by the start of the next character token here. 60 //So, we already have advanced position. 61 this.currentCharacterToken.location.end = this.preprocessor.pos; 62 } 63 64 tokenizerProto._emitCurrentCharacterToken.call(this); 65 }; 66 67 //NOTE: patch initial states for each mode to obtain token start position 68 Object.keys(tokenizerProto.MODE) 69 70 .map(function (modeName) { 71 return tokenizerProto.MODE[modeName]; 72 }) 73 74 .forEach(function (state) { 75 tokenizer[state] = function (cp) { 76 this.tokenStartLoc = this.preprocessor.pos; 77 tokenizerProto[state].call(this, cp); 78 }; 79 }); 80}; 81