context-parser-handlebars
Advanced tools
Comparing version 1.0.5 to 1.0.6
{ | ||
"name": "context-parser-handlebars", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"licenses": [ | ||
@@ -5,0 +5,0 @@ { |
@@ -37,2 +37,15 @@ /* | ||
// extracted from xss-filters | ||
/* | ||
['^(?:', | ||
[ | ||
'[\\u0000-\\u0020]', | ||
'&#[xX]0*(?:1?[1-9a-fA-F]|10|20);?', // -20 in hex | ||
'�*(?:[1-9]|[1-2][0-9]|30|31|32);?', // -32 in dec | ||
'	', '
' // space, newline in char entities | ||
].join('|'), | ||
')*'].join(''); | ||
*/ | ||
var reURIContextStartWhitespaces = /^(?:[\u0000-\u0020]|&#[xX]0*(?:1?[1-9a-fA-F]|10|20);?|�*(?:[1-9]|[1-2][0-9]|30|31|32);?|	|
)*/; | ||
/** | ||
@@ -70,3 +83,54 @@ * @module ContextParserHandlebars | ||
// TODO: use util | ||
// @function ContextParser.getInternalState | ||
contextParser.Parser.prototype.getInternalState = function() { | ||
var stateObj = {}; | ||
stateObj.state = this.state; | ||
stateObj.tagNames = this.tagNames; | ||
stateObj.tagNameIdx = this.tagNameIdx; | ||
stateObj.attributeName = this.attributeName; | ||
stateObj.attributeValue = this.attributeValue; | ||
return stateObj; | ||
}; | ||
// @function ContextParser.setInternalState | ||
contextParser.Parser.prototype.setInternalState = function(stateObj) { | ||
// TODO: these 2 apis need to combine. | ||
this.setInitState(stateObj.state); | ||
this.setCurrentState(stateObj.state); | ||
this.tagNames = stateObj.tagNames.slice(0); // need deep copy | ||
this.tagNameIdx = stateObj.tagNameIdx; | ||
this.attributeName = stateObj.attributeName; | ||
this.attributeValue = stateObj.attributeValue; | ||
}; | ||
// @function ContextParser._deepCompareState | ||
contextParser.Parser.prototype._deepCompareState = function(stateObj1, stateObj2) { | ||
var r = true; | ||
[ 'state', // test for the HTML5 state. | ||
// 'tagNameIdx', // test for the close tag in the branching logic, but it is not balanced. | ||
// 'attributeName', 'attributeValue' // not necessary the same in branching logic. | ||
].some(function(key) { | ||
if (stateObj1[key] !== '' && stateObj2[key] !== '' && stateObj1[key] !== stateObj2[key]) { | ||
r = false; | ||
} | ||
}); | ||
/* | ||
[ | ||
// 'tagNames' // not necessary the same in branching logic. | ||
].forEach(function(key) { | ||
if (!(stateObj1[key] instanceof Array) || !(stateObj2[key] instanceof Array)) { | ||
r = false; | ||
return; | ||
} | ||
for(var i=0;i<stateObj1[key].length;++i) { | ||
if (stateObj1[key][i] !== stateObj2[key][i]) { | ||
r = false; | ||
} | ||
} | ||
}); | ||
*/ | ||
return r; | ||
}; | ||
/* inherit the prototype of contextParser.Parser */ | ||
@@ -145,3 +209,3 @@ ContextParserHandlebars.prototype = Object.create(contextParser.Parser.prototype); | ||
/* transitent var */ | ||
var e, f, msg, exceptionObj; | ||
var isFullUri, f, msg, exceptionObj; | ||
@@ -156,186 +220,167 @@ /* return filters */ | ||
// 1 | ||
if (state === stateMachine.State.STATE_DATA) { | ||
filters.push(filter.FILTER_DATA); | ||
return filters; | ||
// 3 | ||
} else if (state === stateMachine.State.STATE_RCDATA) { | ||
filters.push(filter.FILTER_DATA); | ||
return filters; | ||
// 5 | ||
} else if (state === stateMachine.State.STATE_RAWTEXT) { | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_RAWTEXT state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 6 | ||
} else if (state === stateMachine.State.STATE_SCRIPT_DATA) { | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_SCRIPT_DATA state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 34 | ||
} else if (state === stateMachine.State.STATE_BEFORE_ATTRIBUTE_NAME) { | ||
/* never fall into this state */ | ||
// 35 | ||
} else if (state === stateMachine.State.STATE_ATTRIBUTE_NAME) { | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_ATTRIBUTE_NAME state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 36 | ||
} else if (state === stateMachine.State.STATE_AFTER_ATTRIBUTE_NAME) { | ||
/* never fall into this state, please refer to tests/unit/run-states-spec.js */ | ||
// 37 | ||
} else if (state === stateMachine.State.STATE_BEFORE_ATTRIBUTE_VALUE) { | ||
/* never fall into this state, please refer to tests/unit/run-states-spec.js */ | ||
// 38, 39, 40 + URI scheme | ||
} else if ((state === stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED) && | ||
(attributeName === "href" || attributeName === "src" || attributeName === "action" || attributeName === "formaction" || attributeName === "background" || attributeName === "cite" || attributeName === "longdesc" || attributeName === "usemap" || attributeName === "xlink:href") | ||
) { | ||
/* we don't support javascript parsing yet */ | ||
// TODO: this filtering rule cannot cover all cases. | ||
if (handlebarsUtils.blacklistProtocol(attributeValue)) { | ||
switch(state) { | ||
case stateMachine.State.STATE_DATA: // 1 | ||
filters.push(filter.FILTER_DATA); | ||
return filters; | ||
case stateMachine.State.STATE_RCDATA: // 3 | ||
filters.push(filter.FILTER_DATA); | ||
return filters; | ||
case stateMachine.State.STATE_RAWTEXT: // 5 | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attribute URI Javascript context."; | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_RAWTEXT state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
/* this one is safe to return */ | ||
return filters; | ||
} | ||
case stateMachine.State.STATE_SCRIPT_DATA: // 6 | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_SCRIPT_DATA state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_BEFORE_ATTRIBUTE_NAME: // 34 | ||
/* never fall into state 34 */ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unexpected output expression @ STATE_BEFORE_ATTRIBUTE_NAME state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_ATTRIBUTE_NAME: // 35 | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_ATTRIBUTE_NAME state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_AFTER_ATTRIBUTE_NAME: // 36 | ||
/* never fall into state 36 */ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unexpected output expression @ STATE_AFTER_ATTRIBUTE_NAME state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_BEFORE_ATTRIBUTE_VALUE: // 37 | ||
/* never fall into state 37 */ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unexpected output expression @ STATE_BEFORE_ATTRIBUTE_VALUE state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: // 38 | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: // 39 | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED: // 40 | ||
/* add the correct uri filter */ | ||
var isFullUri = true; | ||
if (attributeValue.trim() === "") { | ||
f = filter.FILTER_FULL_URI; | ||
} else { | ||
isFullUri = false; | ||
f = filter.FILTER_ENCODE_URI; | ||
e = attributeValue.length; | ||
for(var i=0;i<e;++i) { | ||
if (attributeValue[i] === '=') { | ||
f = filter.FILTER_ENCODE_URI_COMPONENT; | ||
// URI scheme | ||
if (attributeName === "href" || attributeName === "src" || attributeName === "action" || | ||
attributeName === "formaction" || attributeName === "background" || attributeName === "cite" || | ||
attributeName === "longdesc" || attributeName === "usemap" || attributeName === "xlink:href" | ||
) { | ||
/* we don't support javascript parsing yet */ | ||
// TODO: this filtering rule cannot cover all cases. | ||
if (handlebarsUtils.blacklistProtocol(attributeValue)) { | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attribute URI Javascript context."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
/* this one is safe to return */ | ||
return filters; | ||
} | ||
} | ||
} | ||
filters.push(f); | ||
/* add the attribute value filter */ | ||
f = filter.FILTER_NOT_HANDLE; | ||
switch(state) { | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_UNQUOTED; | ||
break; | ||
default: | ||
break; | ||
} | ||
filters.push(f); | ||
/* add the correct uri filter */ | ||
if (attributeValue.replace(reURIContextStartWhitespaces, '') === "") { | ||
isFullUri = true; | ||
f = filter.FILTER_FULL_URI; | ||
} else { | ||
isFullUri = false; | ||
f = (attributeValue.indexOf('=') === -1) ? filter.FILTER_ENCODE_URI : filter.FILTER_ENCODE_URI_COMPONENT; | ||
} | ||
filters.push(f); | ||
/* add blacklist filters at the end of filtering chain */ | ||
if (isFullUri) { | ||
/* blacklist the URI scheme for full uri */ | ||
filters.push(filter.FILTER_URI_SCHEME_BLACKLIST); | ||
} | ||
/* add the attribute value filter */ | ||
f = filter.FILTER_NOT_HANDLE; | ||
switch(state) { | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_UNQUOTED; | ||
break; | ||
default: | ||
break; | ||
} | ||
filters.push(f); | ||
return filters; | ||
// 38, 39, 40 + CSS spec | ||
} else if ((state === stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED) && | ||
(attributeName === "style")) { | ||
/* we don't support css parser yet | ||
* | ||
* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attribute style CSS context."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 38, 39, 40 + Javascript spec | ||
} else if ((state === stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED) && | ||
(attributeName.match(/^on/i))) { | ||
/* we don't support js parser yet | ||
* | ||
* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attrubute on* Javascript context."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 38, 39, 40 ONLY and should be placed at last. | ||
} else if (state === stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED || | ||
state === stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED) { | ||
/* add the attribute value filter */ | ||
f = filter.FILTER_NOT_HANDLE; | ||
switch(state) { | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_UNQUOTED; | ||
break; | ||
default: | ||
break; | ||
} | ||
filters.push(f); | ||
return filters; | ||
// 42 | ||
} else if (state === stateMachine.State.STATE_AFTER_ATTRIBUTE_VALUE_QUOTED) { | ||
/* | ||
* please refer to tests/unit/run-states-spec.js, '{' triggers state change to 12.2.4.34 | ||
* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_AFTER_ATTRIBUTE_VALUE_QUOTED state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
// 48 | ||
} else if (state === stateMachine.State.STATE_COMMENT) { | ||
filters.push(filter.FILTER_COMMENT); | ||
return filters; | ||
/* add blacklist filters at the end of filtering chain */ | ||
if (isFullUri) { | ||
/* blacklist the URI scheme for full uri */ | ||
filters.push(filter.FILTER_URI_SCHEME_BLACKLIST); | ||
} | ||
return filters; | ||
} else if (attributeName === "style") { // CSS | ||
/* we don't support css parser yet | ||
* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attribute style CSS context."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
} else if (attributeName.match(/^on/i)) { // Javascript | ||
/* we don't support js parser yet | ||
* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ attrubute on* Javascript context."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
} else { | ||
/* add the attribute value filter */ | ||
f = filter.FILTER_NOT_HANDLE; | ||
switch(state) { | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_DOUBLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_SINGLE_QUOTED; | ||
break; | ||
case stateMachine.State.STATE_ATTRIBUTE_VALUE_UNQUOTED: | ||
f = filter.FILTER_ATTRIBUTE_VALUE_UNQUOTED; | ||
break; | ||
default: | ||
break; | ||
} | ||
filters.push(f); | ||
return filters; | ||
} | ||
break; | ||
case stateMachine.State.STATE_AFTER_ATTRIBUTE_VALUE_QUOTED: // 42 | ||
/* never fall into state 42 */ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ STATE_AFTER_ATTRIBUTE_VALUE_QUOTED state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
case stateMachine.State.STATE_COMMENT: // 48 | ||
filters.push(filter.FILTER_COMMENT); | ||
return filters; | ||
default: | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ NOT HANDLE state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
} | ||
/* we use filter.FILTER_NOT_HANDLE to warn the developers for unsafe output expression, | ||
* and we fall back to default Handlebars escaping filter. IT IS UNSAFE. | ||
*/ | ||
filters.push(filter.FILTER_NOT_HANDLE); | ||
msg = "[WARNING] ContextParserHandlebars: Unsafe output expression @ NOT HANDLE state."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, this._strictMode); | ||
return filters; | ||
}; | ||
@@ -351,4 +396,6 @@ | ||
len = input.length, | ||
str = '', t = 0, | ||
str = '', | ||
obj = {}; | ||
obj.str = ''; | ||
for(var j=i;j<len;++j) { | ||
@@ -358,14 +405,8 @@ switch (type) { | ||
if (input[j] === '-' && j+3<len && input[j+1] === '-' && input[j+2] === '}' && input[j+3] === '}') { | ||
printChar === true ? this._printChar('--}}') : str += '--}}'; | ||
j=j+3; | ||
obj.index = j; | ||
obj.str = str; | ||
printChar === true ? this._printChar('--}}') : obj.str += '--}}'; | ||
obj.index = j+3; | ||
return obj; | ||
} else if (input[j] === '-' && j+4<len && input[j+1] === '-' && input[j+2] === '~' && input[j+3] === '}' && input[j+4] === '}') { | ||
printChar === true ? this._printChar('--~}}') : str += '--~}}'; | ||
j=j+4; | ||
obj.index = j; | ||
obj.str = str; | ||
printChar === true ? this._printChar('--~}}') : obj.str += '--~}}'; | ||
obj.index = j+4; | ||
return obj; | ||
@@ -376,10 +417,8 @@ } | ||
if (input[j] === '}' && j+2<len && input[j+1] === '}' && input[j+2] === '}') { | ||
printChar === true ? this._printChar('}}}') : str += '}}}'; | ||
j=j+2; | ||
obj.index = j; | ||
obj.str = str; | ||
printChar === true ? this._printChar('}}}') : obj.str += '}}}'; | ||
obj.index = j+2; | ||
return obj; | ||
} | ||
break; | ||
case handlebarsUtils.NOT_HANDLE_EXPRESSION: | ||
case handlebarsUtils.ESCAPE_EXPRESSION: | ||
@@ -393,7 +432,4 @@ case handlebarsUtils.PARTIAL_EXPRESSION: | ||
if (input[j] === '}' && j+1<len && input[j+1] === '}') { | ||
printChar === true ? this._printChar('}}') : str += '}}'; | ||
j=j+1; | ||
obj.index = j; | ||
obj.str = str; | ||
printChar === true ? this._printChar('}}') : obj.str += '}}'; | ||
obj.index = j+1; | ||
return obj; | ||
@@ -403,3 +439,3 @@ } | ||
} | ||
printChar === true ? this._printChar(input[j]) : str += input[j]; | ||
printChar === true ? this._printChar(input[j]) : obj.str += input[j]; | ||
} | ||
@@ -412,3 +448,3 @@ msg = "[ERROR] ContextParserHandlebars: Parsing error! Cannot encounter close brace of expression."; | ||
// @function module:ContextParserHandlebars._handleEscapeExpression | ||
ContextParserHandlebars.prototype._handleEscapeExpression = function(input, i, len, state) { | ||
ContextParserHandlebars.prototype._handleEscapeExpression = function(input, i, len, nextState) { | ||
var msg, exceptionObj, | ||
@@ -427,3 +463,3 @@ str = '{{', | ||
var stateObj = this.getInternalState(); | ||
filters = this._addFilters(state, stateObj, input); | ||
filters = this._addFilters(nextState, stateObj, input); | ||
for(var k=filters.length-1;k>=0;--k) { | ||
@@ -510,3 +546,3 @@ if (re.isSingleID && k === 0) { | ||
// @function module:ContextParserHandlebars._handleBranchExpression | ||
ContextParserHandlebars.prototype._handleBranchExpression = function(input, i, state) { | ||
ContextParserHandlebars.prototype._handleBranchExpression = function(input, i) { | ||
var msg, exceptionObj, | ||
@@ -531,3 +567,3 @@ obj = {}; | ||
debug("_handleBranchTemplate: state:"+this.state+",new i:"+ast.index+",lineNo:"+this._lineNo); | ||
debug("_handleBranchTemplate: state:"+result.lastStates[0].state+",new i:"+ast.index+",lineNo:"+this._lineNo); | ||
return obj; | ||
@@ -540,56 +576,2 @@ } catch (err) { | ||
// TODO: context-parser dependent, should move back to context-parser later | ||
// @function ContextParserHandlebars.getInternalState | ||
ContextParserHandlebars.prototype.getInternalState = function() { | ||
var stateObj = {}; | ||
stateObj.state = this.state; | ||
stateObj.tagNames = this.tagNames; | ||
stateObj.tagNameIdx = this.tagNameIdx; | ||
stateObj.attributeName = this.attributeName; | ||
stateObj.attributeValue = this.attributeValue; | ||
return stateObj; | ||
}; | ||
// TODO: context-parser dependent, should move back to context-parser later | ||
// @function ContextParserHandlebars.setInternalState | ||
ContextParserHandlebars.prototype.setInternalState = function(stateObj) { | ||
// TODO: these 2 apis need to combine. | ||
this.setInitState(stateObj.state); | ||
this.setCurrentState(stateObj.state); | ||
this.tagNames = stateObj.tagNames; | ||
this.tagNameIdx = stateObj.tagNameIdx; | ||
this.attributeName = stateObj.attributeName; | ||
this.attributeValue = stateObj.attributeValue; | ||
}; | ||
// TODO: context-parser dependent, should move back to context-parser later | ||
// @function ContextParserHandlebars._deepCompareState | ||
ContextParserHandlebars.prototype._deepCompareState = function(stateObj1, stateObj2) { | ||
var r = true; | ||
[ 'state', | ||
'tagNameIdx', | ||
// attributeName/Value does not affect the state transition | ||
// 'attributeName', 'attributeValue' | ||
].forEach(function(key) { | ||
if (stateObj1[key] !== '' && stateObj2[key] !== '' && stateObj1[key] !== stateObj2[key]) { | ||
r = false; | ||
} | ||
}); | ||
[ | ||
'tagNames' | ||
].forEach(function(key) { | ||
if (!(stateObj1[key] instanceof Array) || !(stateObj2[key] instanceof Array)) { | ||
r = false; | ||
return; | ||
} | ||
for(var i=0;i<stateObj1.length;++i) { | ||
if (stateObj1[key][i] !== stateObj2[key][i]) { | ||
r = false; | ||
} | ||
} | ||
}); | ||
return r; | ||
}; | ||
// @function module:ContextParserHandlebars._analyzeContext | ||
@@ -656,3 +638,2 @@ ContextParserHandlebars.prototype._analyzeContext = function(stateObj, obj) { | ||
debugBranch("_analyzeBranchAst:after:program:content"); | ||
debugBranch(r.lastStates[0]); | ||
@@ -670,3 +651,2 @@ | ||
debugBranch("_analyzeBranchAst:after:program:node"); | ||
debugBranch(r.lastStates[0]); | ||
@@ -694,3 +674,2 @@ | ||
debugBranch("_analyzeBranchAst:after:inverse:content"); | ||
debugBranch(r.lastStates[1]); | ||
@@ -708,3 +687,2 @@ | ||
debugBranch("_analyzeBranchAst:before:inverse:node"); | ||
debugBranch(r.lastStates[1]); | ||
@@ -729,5 +707,7 @@ | ||
if (!this._deepCompareState(r.lastStates[0], r.lastStates[1])) { | ||
msg = "[ERROR] ContextParserHandlebars: Parsing error! Inconsitent HTML5 state after conditional branches. Please fix your template! \n"; | ||
msg += "[ERROR] #if.. branch: " + programDebugOutput.slice(0, 50) + "... ("+JSON.stringify(r.lastStates[0])+"\n"; | ||
msg += "[ERROR] else branch: " + inverseDebugOutput.slice(0, 50) + "... ("+JSON.stringify(r.lastStates[1])+")"; | ||
msg = "[ERROR] ContextParserHandlebars: Parsing error! Inconsitent HTML5 state OR without close tag after conditional branches. Please fix your template! \n"; | ||
msg += "[ERROR] #if branch: " + programDebugOutput.slice(0, 50) + "...\n"; | ||
msg += "[ERROR] else branch: " + inverseDebugOutput.slice(0, 50) + "...\n"; | ||
msg += JSON.stringify(r.lastStates[0]) + "\n"; | ||
msg += JSON.stringify(r.lastStates[1]) + "\n"; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
@@ -941,3 +921,3 @@ handlebarsUtils.handleError(exceptionObj, true); | ||
*/ | ||
ContextParserHandlebars.prototype._handleTemplate = function(input, i, state) { | ||
ContextParserHandlebars.prototype._handleTemplate = function(input, i, nextState) { | ||
@@ -968,3 +948,3 @@ /* the max length of the input string */ | ||
/* _handleRawBlock */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._handleRawBlock(input, i); | ||
@@ -984,6 +964,6 @@ /* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
/* _handleRawExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
/* update the Context Parser's state if it is raw expression. */ | ||
this.state = state; | ||
this.state = nextState; | ||
/* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
@@ -996,2 +976,12 @@ return obj.index+1; | ||
switch (handlebarsExpressionType) { | ||
case handlebarsUtils.NOT_HANDLE_EXPRESSION: | ||
msg = "[WARNING] ContextParserHandlebars: Not supported expression."; | ||
exceptionObj = new ContextParserHandlebarsException(msg, this._lineNo, this._charNo); | ||
handlebarsUtils.handleError(exceptionObj, false); | ||
/* _consumeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
/* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
return obj.index+1; | ||
case handlebarsUtils.ESCAPE_EXPRESSION: | ||
@@ -1005,6 +995,6 @@ re = handlebarsUtils.isValidExpression(input, i, handlebarsExpressionType); | ||
/* _handleEscapeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
obj = this._handleEscapeExpression(input, i, len, state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._handleEscapeExpression(input, i, len, nextState); | ||
/* update the Context Parser's state if it is raw expression. */ | ||
this.state = state; | ||
this.state = nextState; | ||
/* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
@@ -1021,3 +1011,3 @@ return obj.index+1; | ||
/* _consumeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
@@ -1035,3 +1025,3 @@ /* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
/* _consumeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
@@ -1049,4 +1039,4 @@ /* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
/* _handleBranchExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
obj = this._handleBranchExpression(input, i, state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._handleBranchExpression(input, i); | ||
/* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
@@ -1064,3 +1054,3 @@ return obj.index+1; | ||
/* _consumeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
@@ -1073,3 +1063,3 @@ /* advance the index pointer by 1 to the char after the last brace of expression. */ | ||
/* _consumeExpression */ | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+state); | ||
debug("_handleTemplate:handlebarsExpressionType:"+handlebarsExpressionType,",i:"+i+",state:"+nextState); | ||
obj = this._consumeExpression(input, i, handlebarsExpressionType, true); | ||
@@ -1076,0 +1066,0 @@ /* advance the index pointer by 1 to the char after the last brace of expression. */ |
@@ -24,2 +24,4 @@ /* | ||
/* type of expression */ | ||
HandlebarsUtils.UNHANDLED_EXPRESSION = -1; | ||
HandlebarsUtils.NOT_EXPRESSION = 0; | ||
@@ -74,37 +76,30 @@ | ||
var len = input.length, | ||
re; | ||
j; | ||
/* reserved char must be the immediate char right after brace */ | ||
if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '>') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '>') | ||
) { | ||
return HandlebarsUtils.PARTIAL_EXPRESSION; | ||
} else if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '#') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '#') | ||
) { | ||
return HandlebarsUtils.BRANCH_EXPRESSION; | ||
} else if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '^') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '^') | ||
) { | ||
// this one is not exact, {{~?^}} will pass! | ||
return HandlebarsUtils.BRANCH_EXPRESSION; | ||
} else if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '/') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '/') | ||
) { | ||
return HandlebarsUtils.BRANCH_END_EXPRESSION; | ||
} else if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '&') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '&') | ||
) { | ||
return HandlebarsUtils.REFERENCE_EXPRESSION; | ||
} else if ((input[i] === '{' && i+4<len && input[i+1] === '{' && input[i+2] === '!' && input[i+3] === '-' && input[i+4] === '-') || | ||
(input[i] === '{' && i+5<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '!' && input[i+4] === '-' && input[i+5] === '-') | ||
) { | ||
return HandlebarsUtils.COMMENT_EXPRESSION_LONG_FORM; | ||
} else if ((input[i] === '{' && i+2<len && input[i+1] === '{' && input[i+2] === '!') || | ||
(input[i] === '{' && i+3<len && input[i+1] === '{' && input[i+2] === '~' && input[i+3] === '!') | ||
) { | ||
return HandlebarsUtils.COMMENT_EXPRESSION_SHORT_FORM; | ||
if (input[i] === '{' && i+2<len && input[i+1] === '{') { | ||
j = input[i+2] === '~' ? 3 : 2; | ||
switch(input[i+j]) { | ||
case '>': | ||
return HandlebarsUtils.PARTIAL_EXPRESSION; | ||
case '#': | ||
return HandlebarsUtils.BRANCH_EXPRESSION; | ||
case '^': | ||
// {{~?^}} will pass!, but isValidExpression can guard against | ||
return HandlebarsUtils.BRANCH_EXPRESSION; | ||
case '/': | ||
return HandlebarsUtils.BRANCH_END_EXPRESSION; | ||
case '&': | ||
return HandlebarsUtils.REFERENCE_EXPRESSION; | ||
case '!': | ||
if (i+j+2<len && input[i+j+1] === '-' && input[i+j+2] === '-') { | ||
return HandlebarsUtils.COMMENT_EXPRESSION_LONG_FORM; | ||
} | ||
return HandlebarsUtils.COMMENT_EXPRESSION_SHORT_FORM; | ||
default: | ||
return HandlebarsUtils.ESCAPE_EXPRESSION; | ||
} | ||
} | ||
return HandlebarsUtils.ESCAPE_EXPRESSION; | ||
return HandlebarsUtils.UNHANDLED_EXPRESSION; | ||
}; | ||
@@ -187,11 +182,7 @@ | ||
var ch = input[i]; | ||
if (ch === '~' && input.length > i+1) { | ||
if (ch === '~' && i+1<input.length) { | ||
ch = input[i+1]; | ||
} | ||
if (ch === '#' || ch === '/' || ch === '>' || ch === '^' || ch === '!' || ch === '&') { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
return (ch === '#' || ch === '/' || ch === '>' || ch === '^' || ch === '!' || ch === '&'); | ||
}; | ||
@@ -198,0 +189,0 @@ |
@@ -107,5 +107,11 @@ /* | ||
{ | ||
title: '/bin/handlebarspc html5 inconsistent state test', | ||
title: '/bin/handlebarspc html5 inconsistent state (42/34) test', | ||
file: './tests/samples/bugs/003.html5.inconsitent.hb', | ||
}, | ||
/* remove this test as we don't test for tagNameIdx in deepCompare | ||
{ | ||
title: 'state (missing close tag) in branching template test', | ||
file: './tests/samples/bugs/006.state.missing-close-tag.hb', | ||
}, | ||
*/ | ||
].forEach(function(testObj) { | ||
@@ -124,21 +130,9 @@ it(testObj.title, function(done) { | ||
[ | ||
/* remove unnecessary test | ||
{ | ||
title: '/bin/handlebarspc html5 inconsistent state test', | ||
file: './tests/samples/bugs/001.hbs', | ||
result: [], | ||
title: './bin/handlebarspc line no and char no reporting test', | ||
file: './tests/samples/bugs/005.line.report.hb', | ||
result: [ /lineNo:2,charNo:38/, /lineNo:4,charNo:91/, /lineNo:8,charNo:177/, /lineNo:10,charNo:274/, /lineNo:12,charNo:298/ ], | ||
}, | ||
{ | ||
title: '/bin/handlebarspc html5 inconsistent state test', | ||
file: './tests/samples/bugs/001.hbs.original', | ||
result: [], | ||
}, | ||
{ | ||
title: '/bin/handlebarspc html5 inconsistent state test', | ||
file: './tests/samples/bugs/002.hbs', | ||
result: [], | ||
}, | ||
*/ | ||
{ | ||
title: './bin/handlebarspc html5 inconsistent state test', | ||
title: 'state (tag name) propagation in branching template test', | ||
file: './tests/samples/bugs/004.script.hb', | ||
@@ -148,9 +142,4 @@ result: [], | ||
{ | ||
title: './bin/handlebarspc line no and char no reporting test', | ||
file: './tests/samples/bugs/005.line.report.hb', | ||
result: [ /lineNo:2,charNo:38/, /lineNo:4,charNo:91/, /lineNo:8,charNo:177/, /lineNo:10,charNo:274/, /lineNo:12,charNo:298/ ], | ||
}, | ||
{ | ||
title: 'state (attribute name) propagation in logical template test', | ||
file: './tests/samples/bugs/006.state.hb', | ||
title: 'state (attribute name) propagation in branching template test', | ||
file: './tests/samples/bugs/006.state.attribute-name.hb', | ||
result: [ /{{{y styleoutput}}}/, /{{{yavd classoutput}}}/ ], | ||
@@ -157,0 +146,0 @@ }, |
@@ -19,100 +19,106 @@ /* | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.34 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.34 is 12.2.4.1 (>,EOF), 12.2.4.35 (a-zA-Z,null,",',<,=,anything) and 12.2.4.43 (/), | ||
* as 'anything' triggers the state change to 12.2.4.35, so we need to handle this state accordingly | ||
* | ||
* this test is to simulate the case of transitting to the before-attribute-name-state (12.2.4.34) from | ||
* attribute-value-(quoted)-state (12.2.4.40), after-attribute-value-(quoted)-state (12.2.4.42) and | ||
* self-closing start tag state (12.2.4.43), as output place holder cannot be put at the state 34, | ||
* we don't need to handle it (exception). | ||
*/ | ||
it('HTML5 Context Parser placeholder after before-attribute-name-state (12.2.4.34) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<div id="1" {'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,34,35,35,37,38,38,42,34,35'); | ||
it('HTML5 Context Parser placeholder TO before-attribute-name-state (12.2.4.34) test', function(){ | ||
[ | ||
{ html: '<option value=123 {', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,40,40,40,34,35'}, | ||
{ html: '<option value="123" {', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,38,38,42,34,35'}, | ||
{ html: '<option value="123"/ {', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,38,38,42,34,34,35'}, | ||
{ html: '<option value="123"/', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,38,38,42,43'}, | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.36 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.36 is 12.2.4.1 (>,EOF), 12.2.4.35 (a-zA-Z,null,",',<,anything), 12.2.4.37 (=) and 12.2.4.43 (/), | ||
* as 'anything' triggers the state change to 12.2.4.35, so we need to handle this state accordingly | ||
* | ||
* this test is to simulate the case of transitting to the attribute-name-state (12.2.4.35) from | ||
* before-attribute-name-state (12.2.4.34) and after-attribute-name-state (12.2.4.36), | ||
* so we need to handle the state 35. | ||
*/ | ||
it('HTML5 Context Parser placeholder after after-attribute-name-state (12.2.4.36) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<option value="1" selected {'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,42,34,35,35,35,35,35,35,35,35,36,35'); | ||
it('HTML5 Context Parser placeholder TO attribute-name-state (12.2.4.35) test', function(){ | ||
[ | ||
{ html: '<div id="1" {', states: '1,8,10,10,10,34,35,35,37,38,38,42,34,35'}, | ||
{ html: '<option value="1" selected {', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,42,34,35,35,35,35,35,35,35,35,36,35'}, | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.37 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.37 is 12.2.4.1 (>,EOF), 12.2.4.38 ("), 12.2.4.39 ('), and 12.2.4.40 (&,null,<,=,`,anything), | ||
* as 'anything' triggers the state change to 12.2.4.40, so we need to handle this state accordingly | ||
* | ||
* this test is to simulate the case of transitting to the after-attribute-name-state (12.2.4.36) from | ||
* attribute-name-state (12.2.4.35), as output place holder cannot be put at the state 36, | ||
* we don't need to handle it (exception). | ||
*/ | ||
it('HTML5 Context Parser placeholder after before-attribute-value-state (12.2.4.37) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<option value={'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,40'); | ||
it('HTML5 Context Parser placeholder TO after-attribute-name-state (12.2.4.36) test', function(){ | ||
[ | ||
{ html: '<option value="1" selected ', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,42,34,35,35,35,35,35,35,35,35,36'}, | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.38 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.38 is 12.2.4.1 (EOF) and 12.2.4.42 ("), | ||
* as 'anything' does not trigger the state change, so we need to handle this state accordingly | ||
* | ||
* this test is to simulate the case of transitting to the before-attribute-value-state (12.2.4.37) from | ||
* attribute-name-state (12.2.4.35) and after-attribute-name-value-state (12.2.4.36), | ||
* as output place holder cannot be put at the state 37, we don't need to handle it. | ||
*/ | ||
it('HTML5 Context Parser placeholder after attribute-value-(double-quoted)-state (12.2.4.38) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<option value="{'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38'); | ||
it('HTML5 Context Parser placeholder TO before-attribute-value-state (12.2.4.37) test', function(){ | ||
[ | ||
{ html: '<option value=', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37'}, | ||
{ html: '<option value =', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,36,37'}, | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.39 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.39 is 12.2.4.1 (EOF) and 12.2.4.42 ('), | ||
* as 'anything' does not trigger the state change, so we need to handle this state accordingly | ||
* | ||
* this test is to simulate the case of transitting to the attribute-value-(double-quoted)-state (12.2.4.38), | ||
* attribute-value-(single-quoted)-state (12.2.4.39), attribute-value-(unquoted)-state (12.2.4.40) | ||
* so we need to handle the state 38,39 and 40. | ||
*/ | ||
it('HTML5 Context Parser placeholder after attribute-value-(single-quoted)-state (12.2.4.39) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<option value=\'{'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,39,39'); | ||
it('HTML5 Context Parser placeholder TO attribute-value-(double/single/un-quoted)-state (12.2.4.38/39/40) test', function(){ | ||
[ | ||
{ html: '<option value="{', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38'}, | ||
{ html: "<option value='{", states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,39,39'}, | ||
{ html: '<option value={', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,40'} | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
/* | ||
* this test is to simulate the case that the developer is putting the output place holder after | ||
* the state 12.2.4.42 and test what correct filter should be applied. | ||
* | ||
* the next state of state 12.2.4.42 is 12.2.4.1 (>,EOF), 12.2.4.34 (space etc,anything), 12.2.4.43 (/), | ||
* however, 'anything' triggers the state change to 12.2.4.34 and reconsume logic, | ||
* it replaces the states buffer with 12.2.4.34, this falls back to the previous handling case above. | ||
* | ||
* this test is to simulate the case of transitting to the after-attribute-value-(quoted)-state (12.2.4.42) from | ||
* attribute-value-(single-quoted)-state (12.2.4.39), attribute-value-(unquoted)-state (12.2.4.40), | ||
* as output place holder cannot be put at the state 42, we don't need to handle it (exception). | ||
*/ | ||
it('HTML5 Context Parser after-attribute-value-(quoted)-state (12.2.4.42) test', function(){ | ||
var p1 = new Parser(); | ||
var html = '<div id="1"{'; | ||
p1.contextualize(html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal('1,8,10,10,10,34,35,35,37,38,38,34,35'); | ||
it('HTML5 Context Parser placeholder TO after-attribute-value-(quoted)-state (12.2.4.42) test', function(){ | ||
[ | ||
{ html: '<option value="{}"', states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,38,38,38,42'}, | ||
{ html: "<option value='{}'", states: '1,8,10,10,10,10,10,10,34,35,35,35,35,35,37,39,39,39,42'}, | ||
].forEach(function(testObj) { | ||
var p1 = new Parser(); | ||
p1.contextualize(testObj.html); | ||
var states = p1.getStates(); | ||
expect(states.toString()).to.equal(testObj.states); | ||
}); | ||
}); | ||
}); | ||
}()); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
216993
69
3198