'use strict'; | |
var Tokenizer = require('../tokenization/tokenizer'), | |
TokenizerProxy = require('./tokenizer_proxy'), | |
Utils = require('../common/utils'); | |
//Default options | |
var DEFAULT_OPTIONS = { | |
decodeHtmlEntities: true, | |
locationInfo: false | |
}; | |
//Skipping handler | |
function skip() { | |
//NOTE: do nothing =) | |
} | |
//SimpleApiParser | |
var SimpleApiParser = module.exports = function (handlers, options) { | |
this.options = Utils.mergeOptions(DEFAULT_OPTIONS, options); | |
this.handlers = { | |
doctype: this._wrapHandler(handlers.doctype), | |
startTag: this._wrapHandler(handlers.startTag), | |
endTag: this._wrapHandler(handlers.endTag), | |
text: this._wrapHandler(handlers.text), | |
comment: this._wrapHandler(handlers.comment) | |
}; | |
}; | |
SimpleApiParser.prototype._wrapHandler = function (handler) { | |
var parser = this; | |
handler = handler || skip; | |
if (this.options.locationInfo) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
args.push(parser.currentTokenLocation); | |
handler.apply(handler, args); | |
}; | |
} | |
return handler; | |
}; | |
//API | |
SimpleApiParser.prototype.parse = function (html) { | |
var token = null; | |
this._reset(html); | |
do { | |
token = this.tokenizerProxy.getNextToken(); | |
if (token.type === Tokenizer.CHARACTER_TOKEN || | |
token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN || | |
token.type === Tokenizer.NULL_CHARACTER_TOKEN) { | |
if (this.options.locationInfo) { | |
if (this.pendingText === null) | |
this.currentTokenLocation = token.location; | |
else | |
this.currentTokenLocation.end = token.location.end; | |
} | |
this.pendingText = (this.pendingText || '') + token.chars; | |
} | |
else { | |
this._emitPendingText(); | |
this._handleToken(token); | |
} | |
} while (token.type !== Tokenizer.EOF_TOKEN); | |
}; | |
//Internals | |
SimpleApiParser.prototype._handleToken = function (token) { | |
if (this.options.locationInfo) | |
this.currentTokenLocation = token.location; | |
if (token.type === Tokenizer.START_TAG_TOKEN) | |
this.handlers.startTag(token.tagName, token.attrs, token.selfClosing); | |
else if (token.type === Tokenizer.END_TAG_TOKEN) | |
this.handlers.endTag(token.tagName); | |
else if (token.type === Tokenizer.COMMENT_TOKEN) | |
this.handlers.comment(token.data); | |
else if (token.type === Tokenizer.DOCTYPE_TOKEN) | |
this.handlers.doctype(token.name, token.publicId, token.systemId); | |
}; | |
SimpleApiParser.prototype._reset = function (html) { | |
this.tokenizerProxy = new TokenizerProxy(html, this.options); | |
this.pendingText = null; | |
this.currentTokenLocation = null; | |
}; | |
SimpleApiParser.prototype._emitPendingText = function () { | |
if (this.pendingText !== null) { | |
this.handlers.text(this.pendingText); | |
this.pendingText = null; | |
} | |
}; |