blob: f352ef02154fcb0c456e39b51e22c9fb0aaefe0d [file] [log] [blame]
'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);
};
});
};