From 1c10dc61bb8b7767a6793347828db15b0949dadd Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 29 Aug 2011 11:19:37 -0700 Subject: [PATCH 001/313] Update syntax units so that they contain type information --- build/node-parserlib.js | 45 ++++++++++++++++++++++++++---------- build/parserlib-core.js | 10 ++++++-- build/parserlib-css.js | 35 ++++++++++++++++++++-------- build/parserlib.js | 45 ++++++++++++++++++++++++++---------- src/css/Combinator.js | 2 +- src/css/MediaFeature.js | 2 +- src/css/MediaQuery.js | 2 +- src/css/Parser.js | 12 ++++++++++ src/css/PropertyName.js | 2 +- src/css/PropertyValue.js | 2 +- src/css/PropertyValuePart.js | 2 +- src/css/Selector.js | 2 +- src/css/SelectorPart.js | 2 +- src/css/SelectorSubPart.js | 2 +- src/util/SyntaxUnit.js | 8 ++++++- tests/css/CSSParserTests.htm | 3 +++ 16 files changed, 130 insertions(+), 46 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 3706de72..5cb5d408 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ var parserlib = {}; (function(){ @@ -424,7 +424,7 @@ SyntaxError.prototype = new Error(); * @param {int} line The line of text on which the unit resides. * @param {int} col The column of text on which the unit resides. */ -function SyntaxUnit(text, line, col){ +function SyntaxUnit(text, line, col, type){ /** @@ -448,6 +448,12 @@ function SyntaxUnit(text, line, col){ */ this.text = text; + /** + * The type of syntax unit. + * @type int + * @property type + */ + this.type = type; } /** @@ -917,7 +923,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1079,7 +1085,7 @@ var Colors = { */ function Combinator(text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); /** * The type of modifier. @@ -1291,7 +1297,7 @@ var Level2Properties = { */ function MediaFeature(name, value){ - SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol); + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); /** * The name of the media feature @@ -1325,7 +1331,7 @@ MediaFeature.prototype.constructor = MediaFeature; */ function MediaQuery(modifier, mediaType, features, line, col){ - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col); + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") @@ -1376,6 +1382,18 @@ function Parser(options){ this._tokenStream = null; } +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + + Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -3528,6 +3546,7 @@ var Properties = { "animation-delay": 1, "animation-direction": 1, "animation-duration": 1, + "animation-fill-mode": 1, "animation-iteration-count": 1, "animation-name": 1, "animation-play-state": 1, @@ -3791,6 +3810,8 @@ var Properties = { "transition-property": 1, "transition-timing-function": 1, "unicode-bidi": 1, + "user-modify": 1, + "user-select": 1, "vertical-align": 1, "visibility": 1, "voice-balance": 1, @@ -3845,7 +3866,7 @@ var Properties = { */ function PropertyName(text, hack, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE); /** * The type of IE hack applied ("*", "_", or null). @@ -3875,7 +3896,7 @@ PropertyName.prototype.toString = function(){ */ function PropertyValue(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE); /** * The parts that make up the selector. @@ -3902,7 +3923,7 @@ PropertyValue.prototype.constructor = PropertyValue; */ function PropertyValuePart(text, line, col){ - SyntaxUnit.apply(this,arguments); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE); /** * Indicates the type of value unit. @@ -4046,7 +4067,7 @@ PropertyValuePart.fromToken = function(token){ */ function Selector(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE); /** * The parts that make up the selector. @@ -4078,7 +4099,7 @@ Selector.prototype.constructor = Selector; */ function SelectorPart(elementName, modifiers, text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE); /** * The tag name of the element to which this part @@ -4115,7 +4136,7 @@ SelectorPart.prototype.constructor = SelectorPart; */ function SelectorSubPart(text, type, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE); /** * The type of modifier. diff --git a/build/parserlib-core.js b/build/parserlib-core.js index c699cc68..be9966ac 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ var parserlib = {}; (function(){ @@ -424,7 +424,7 @@ SyntaxError.prototype = new Error(); * @param {int} line The line of text on which the unit resides. * @param {int} col The column of text on which the unit resides. */ -function SyntaxUnit(text, line, col){ +function SyntaxUnit(text, line, col, type){ /** @@ -448,6 +448,12 @@ function SyntaxUnit(text, line, col){ */ this.text = text; + /** + * The type of syntax unit. + * @type int + * @property type + */ + this.type = type; } /** diff --git a/build/parserlib-css.js b/build/parserlib-css.js index dc4df6e2..18616887 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -183,7 +183,7 @@ var Colors = { */ function Combinator(text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); /** * The type of modifier. @@ -395,7 +395,7 @@ var Level2Properties = { */ function MediaFeature(name, value){ - SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol); + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); /** * The name of the media feature @@ -429,7 +429,7 @@ MediaFeature.prototype.constructor = MediaFeature; */ function MediaQuery(modifier, mediaType, features, line, col){ - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col); + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") @@ -480,6 +480,18 @@ function Parser(options){ this._tokenStream = null; } +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + + Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -2632,6 +2644,7 @@ var Properties = { "animation-delay": 1, "animation-direction": 1, "animation-duration": 1, + "animation-fill-mode": 1, "animation-iteration-count": 1, "animation-name": 1, "animation-play-state": 1, @@ -2895,6 +2908,8 @@ var Properties = { "transition-property": 1, "transition-timing-function": 1, "unicode-bidi": 1, + "user-modify": 1, + "user-select": 1, "vertical-align": 1, "visibility": 1, "voice-balance": 1, @@ -2949,7 +2964,7 @@ var Properties = { */ function PropertyName(text, hack, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE); /** * The type of IE hack applied ("*", "_", or null). @@ -2979,7 +2994,7 @@ PropertyName.prototype.toString = function(){ */ function PropertyValue(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE); /** * The parts that make up the selector. @@ -3006,7 +3021,7 @@ PropertyValue.prototype.constructor = PropertyValue; */ function PropertyValuePart(text, line, col){ - SyntaxUnit.apply(this,arguments); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE); /** * Indicates the type of value unit. @@ -3150,7 +3165,7 @@ PropertyValuePart.fromToken = function(token){ */ function Selector(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE); /** * The parts that make up the selector. @@ -3182,7 +3197,7 @@ Selector.prototype.constructor = Selector; */ function SelectorPart(elementName, modifiers, text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE); /** * The tag name of the element to which this part @@ -3219,7 +3234,7 @@ SelectorPart.prototype.constructor = SelectorPart; */ function SelectorSubPart(text, type, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE); /** * The type of modifier. diff --git a/build/parserlib.js b/build/parserlib.js index b73a9119..cc1c29ab 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ var parserlib = {}; (function(){ @@ -424,7 +424,7 @@ SyntaxError.prototype = new Error(); * @param {int} line The line of text on which the unit resides. * @param {int} col The column of text on which the unit resides. */ -function SyntaxUnit(text, line, col){ +function SyntaxUnit(text, line, col, type){ /** @@ -448,6 +448,12 @@ function SyntaxUnit(text, line, col){ */ this.text = text; + /** + * The type of syntax unit. + * @type int + * @property type + */ + this.type = type; } /** @@ -917,7 +923,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-July-2011 01:46:47 */ +/* Build time: 29-August-2011 11:18:44 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1079,7 +1085,7 @@ var Colors = { */ function Combinator(text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); /** * The type of modifier. @@ -1291,7 +1297,7 @@ var Level2Properties = { */ function MediaFeature(name, value){ - SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol); + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); /** * The name of the media feature @@ -1325,7 +1331,7 @@ MediaFeature.prototype.constructor = MediaFeature; */ function MediaQuery(modifier, mediaType, features, line, col){ - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col); + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") @@ -1376,6 +1382,18 @@ function Parser(options){ this._tokenStream = null; } +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + + Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -3528,6 +3546,7 @@ var Properties = { "animation-delay": 1, "animation-direction": 1, "animation-duration": 1, + "animation-fill-mode": 1, "animation-iteration-count": 1, "animation-name": 1, "animation-play-state": 1, @@ -3791,6 +3810,8 @@ var Properties = { "transition-property": 1, "transition-timing-function": 1, "unicode-bidi": 1, + "user-modify": 1, + "user-select": 1, "vertical-align": 1, "visibility": 1, "voice-balance": 1, @@ -3845,7 +3866,7 @@ var Properties = { */ function PropertyName(text, hack, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE); /** * The type of IE hack applied ("*", "_", or null). @@ -3875,7 +3896,7 @@ PropertyName.prototype.toString = function(){ */ function PropertyValue(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE); /** * The parts that make up the selector. @@ -3902,7 +3923,7 @@ PropertyValue.prototype.constructor = PropertyValue; */ function PropertyValuePart(text, line, col){ - SyntaxUnit.apply(this,arguments); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE); /** * Indicates the type of value unit. @@ -4046,7 +4067,7 @@ PropertyValuePart.fromToken = function(token){ */ function Selector(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE); /** * The parts that make up the selector. @@ -4078,7 +4099,7 @@ Selector.prototype.constructor = Selector; */ function SelectorPart(elementName, modifiers, text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE); /** * The tag name of the element to which this part @@ -4115,7 +4136,7 @@ SelectorPart.prototype.constructor = SelectorPart; */ function SelectorSubPart(text, type, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE); /** * The type of modifier. diff --git a/src/css/Combinator.js b/src/css/Combinator.js index a0fbc81f..471c595e 100644 --- a/src/css/Combinator.js +++ b/src/css/Combinator.js @@ -10,7 +10,7 @@ */ function Combinator(text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); /** * The type of modifier. diff --git a/src/css/MediaFeature.js b/src/css/MediaFeature.js index 6cdcfdbc..0efd1a7c 100644 --- a/src/css/MediaFeature.js +++ b/src/css/MediaFeature.js @@ -9,7 +9,7 @@ */ function MediaFeature(name, value){ - SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol); + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); /** * The name of the media feature diff --git a/src/css/MediaQuery.js b/src/css/MediaQuery.js index ee2c7468..3ced7360 100644 --- a/src/css/MediaQuery.js +++ b/src/css/MediaQuery.js @@ -12,7 +12,7 @@ */ function MediaQuery(modifier, mediaType, features, line, col){ - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col); + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") diff --git a/src/css/Parser.js b/src/css/Parser.js index 8db6b229..efae15e3 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -21,6 +21,18 @@ function Parser(options){ this._tokenStream = null; } +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + + Parser.prototype = function(){ var proto = new EventTarget(), //new prototype diff --git a/src/css/PropertyName.js b/src/css/PropertyName.js index 402f4f98..e9bd351d 100644 --- a/src/css/PropertyName.js +++ b/src/css/PropertyName.js @@ -11,7 +11,7 @@ */ function PropertyName(text, hack, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE); /** * The type of IE hack applied ("*", "_", or null). diff --git a/src/css/PropertyValue.js b/src/css/PropertyValue.js index 3f14d4f5..c9f1d536 100644 --- a/src/css/PropertyValue.js +++ b/src/css/PropertyValue.js @@ -12,7 +12,7 @@ */ function PropertyValue(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE); /** * The parts that make up the selector. diff --git a/src/css/PropertyValuePart.js b/src/css/PropertyValuePart.js index e2aa20eb..b4467596 100644 --- a/src/css/PropertyValuePart.js +++ b/src/css/PropertyValuePart.js @@ -11,7 +11,7 @@ */ function PropertyValuePart(text, line, col){ - SyntaxUnit.apply(this,arguments); + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE); /** * Indicates the type of value unit. diff --git a/src/css/Selector.js b/src/css/Selector.js index 2511726d..0d6b6a06 100644 --- a/src/css/Selector.js +++ b/src/css/Selector.js @@ -11,7 +11,7 @@ */ function Selector(parts, line, col){ - SyntaxUnit.call(this, parts.join(" "), line, col); + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE); /** * The parts that make up the selector. diff --git a/src/css/SelectorPart.js b/src/css/SelectorPart.js index 2abebb64..409413fd 100644 --- a/src/css/SelectorPart.js +++ b/src/css/SelectorPart.js @@ -16,7 +16,7 @@ */ function SelectorPart(elementName, modifiers, text, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE); /** * The tag name of the element to which this part diff --git a/src/css/SelectorSubPart.js b/src/css/SelectorSubPart.js index f091c3eb..68972297 100644 --- a/src/css/SelectorSubPart.js +++ b/src/css/SelectorSubPart.js @@ -12,7 +12,7 @@ */ function SelectorSubPart(text, type, line, col){ - SyntaxUnit.call(this, text, line, col); + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE); /** * The type of modifier. diff --git a/src/util/SyntaxUnit.js b/src/util/SyntaxUnit.js index 29641ea0..45aac3de 100644 --- a/src/util/SyntaxUnit.js +++ b/src/util/SyntaxUnit.js @@ -7,7 +7,7 @@ * @param {int} line The line of text on which the unit resides. * @param {int} col The column of text on which the unit resides. */ -function SyntaxUnit(text, line, col){ +function SyntaxUnit(text, line, col, type){ /** @@ -31,6 +31,12 @@ function SyntaxUnit(text, line, col){ */ this.text = text; + /** + * The type of syntax unit. + * @type int + * @property type + */ + this.type = type; } /** diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index aee80cd2..bcfd5181 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -40,10 +40,12 @@

CSS Parser Tests

var result = parser.parseSelector("li"); assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + assert.areEqual(Parser.SELECTOR_TYPE, result.type); assert.areEqual(1, result.line, "Line start should be 1"); assert.areEqual(1, result.col, "Column start should be 1"); assert.areEqual(1, result.parts.length, "Selector should have three parts."); assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + assert.areEqual(Parser.SELECTOR_PART_TYPE, result.parts[0].type); assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); }, @@ -53,6 +55,7 @@

CSS Parser Tests

var result = parser.parseSelector("svg|rect"); assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + assert.areEqual(Parser.SELECTOR_TYPE, result.type); assert.areEqual(1, result.line, "Line start should be 1"); assert.areEqual(1, result.col, "Column start should be 1"); assert.areEqual(1, result.parts.length, "Selector should have three parts."); From fad9609c4a2b1011a13e5416dd2d1dc83050b86b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 21 Sep 2011 12:03:19 -0700 Subject: [PATCH 002/313] Fixed JSHint warnings --- build/node-parserlib.js | 37 ++++++++++++++++++++++++++----------- build/parserlib-core.js | 23 +++++++++++++---------- build/parserlib-css.js | 12 +++++++++++- build/parserlib.js | 37 ++++++++++++++++++++++++++----------- src/util/TokenStreamBase.js | 20 +++++++++++--------- 5 files changed, 87 insertions(+), 42 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 5cb5d408..16b47ee9 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ var parserlib = {}; (function(){ @@ -558,14 +558,14 @@ function TokenStreamBase(input, tokenData){ */ TokenStreamBase.createTokenData = function(tokens){ - var nameMap = [], - typeMap = {}, - tokenData = tokens.concat([]), - i = 0, - len = tokenData.length+1; + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; tokenData.UNKNOWN = -1; - tokenData.unshift({name:"EOF"}); + tokenData.unshift({name:"EOF"}); for (; i < len; i++){ nameMap.push(tokenData[i].name); @@ -582,8 +582,8 @@ TokenStreamBase.createTokenData = function(tokens){ tokenData.type = function(c){ return typeMap[c]; }; - - return tokenData; + + return tokenData; }; TokenStreamBase.prototype = { @@ -644,6 +644,8 @@ TokenStreamBase.prototype = { */ mustMatch: function(tokenTypes, channel){ + var token; + //always convert to an array, makes things easier if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; @@ -720,7 +722,7 @@ TokenStreamBase.prototype = { } //call token retriever method - token = this._getToken(); + token = this._getToken(); //if it should be hidden, don't save a token if (token.type > -1 && !tokenInfo[token.type].hide){ @@ -892,6 +894,7 @@ TokenStreamBase.prototype = { }; + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -900,6 +903,7 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); + /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -923,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1111,6 +1115,7 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; + var Level1Properties = { "background": 1, @@ -1317,6 +1322,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; + /** * Represents an individual media query. * @namespace parserlib.css @@ -1359,6 +1365,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; + /** * A CSS3 parser. * @namespace parserlib.css @@ -3882,6 +3889,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; + /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3910,6 +3918,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; + /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4081,6 +4090,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; + /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4122,6 +4132,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; + /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4159,6 +4170,7 @@ SelectorSubPart.prototype.constructor = SelectorSubPart; + var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -5156,6 +5168,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); + var Tokens = [ /* @@ -5362,6 +5375,7 @@ var Tokens = [ + /** * Type to use when a validation error occurs. * @class ValidationError @@ -5417,6 +5431,7 @@ ValidationError :ValidationError }; })(); + (function(){ for(var prop in parserlib){ exports[prop] = parserlib[prop]; diff --git a/build/parserlib-core.js b/build/parserlib-core.js index be9966ac..9c7cf7a7 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ var parserlib = {}; (function(){ @@ -558,14 +558,14 @@ function TokenStreamBase(input, tokenData){ */ TokenStreamBase.createTokenData = function(tokens){ - var nameMap = [], - typeMap = {}, - tokenData = tokens.concat([]), - i = 0, - len = tokenData.length+1; + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; tokenData.UNKNOWN = -1; - tokenData.unshift({name:"EOF"}); + tokenData.unshift({name:"EOF"}); for (; i < len; i++){ nameMap.push(tokenData[i].name); @@ -582,8 +582,8 @@ TokenStreamBase.createTokenData = function(tokens){ tokenData.type = function(c){ return typeMap[c]; }; - - return tokenData; + + return tokenData; }; TokenStreamBase.prototype = { @@ -644,6 +644,8 @@ TokenStreamBase.prototype = { */ mustMatch: function(tokenTypes, channel){ + var token; + //always convert to an array, makes things easier if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; @@ -720,7 +722,7 @@ TokenStreamBase.prototype = { } //call token retriever method - token = this._getToken(); + token = this._getToken(); //if it should be hidden, don't save a token if (token.type > -1 && !tokenInfo[token.type].hide){ @@ -892,6 +894,7 @@ TokenStreamBase.prototype = { }; + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 18616887..f33a9da0 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -209,6 +209,7 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; + var Level1Properties = { "background": 1, @@ -415,6 +416,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; + /** * Represents an individual media query. * @namespace parserlib.css @@ -457,6 +459,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; + /** * A CSS3 parser. * @namespace parserlib.css @@ -2980,6 +2983,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; + /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3008,6 +3012,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; + /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -3179,6 +3184,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; + /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -3220,6 +3226,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; + /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -3257,6 +3264,7 @@ SelectorSubPart.prototype.constructor = SelectorSubPart; + var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -4254,6 +4262,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); + var Tokens = [ /* @@ -4460,6 +4469,7 @@ var Tokens = [ + /** * Type to use when a validation error occurs. * @class ValidationError diff --git a/build/parserlib.js b/build/parserlib.js index cc1c29ab..ef7f9db7 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ var parserlib = {}; (function(){ @@ -558,14 +558,14 @@ function TokenStreamBase(input, tokenData){ */ TokenStreamBase.createTokenData = function(tokens){ - var nameMap = [], - typeMap = {}, - tokenData = tokens.concat([]), - i = 0, - len = tokenData.length+1; + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; tokenData.UNKNOWN = -1; - tokenData.unshift({name:"EOF"}); + tokenData.unshift({name:"EOF"}); for (; i < len; i++){ nameMap.push(tokenData[i].name); @@ -582,8 +582,8 @@ TokenStreamBase.createTokenData = function(tokens){ tokenData.type = function(c){ return typeMap[c]; }; - - return tokenData; + + return tokenData; }; TokenStreamBase.prototype = { @@ -644,6 +644,8 @@ TokenStreamBase.prototype = { */ mustMatch: function(tokenTypes, channel){ + var token; + //always convert to an array, makes things easier if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; @@ -720,7 +722,7 @@ TokenStreamBase.prototype = { } //call token retriever method - token = this._getToken(); + token = this._getToken(); //if it should be hidden, don't save a token if (token.type > -1 && !tokenInfo[token.type].hide){ @@ -892,6 +894,7 @@ TokenStreamBase.prototype = { }; + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -900,6 +903,7 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); + /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -923,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 29-August-2011 11:18:44 */ +/* Build time: 21-September-2011 12:02:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1111,6 +1115,7 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; + var Level1Properties = { "background": 1, @@ -1317,6 +1322,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; + /** * Represents an individual media query. * @namespace parserlib.css @@ -1359,6 +1365,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; + /** * A CSS3 parser. * @namespace parserlib.css @@ -3882,6 +3889,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; + /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3910,6 +3918,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; + /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4081,6 +4090,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; + /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4122,6 +4132,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; + /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4159,6 +4170,7 @@ SelectorSubPart.prototype.constructor = SelectorSubPart; + var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -5156,6 +5168,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); + var Tokens = [ /* @@ -5362,6 +5375,7 @@ var Tokens = [ + /** * Type to use when a validation error occurs. * @class ValidationError @@ -5416,3 +5430,4 @@ Tokens :Tokens, ValidationError :ValidationError }; })(); + diff --git a/src/util/TokenStreamBase.js b/src/util/TokenStreamBase.js index fedbdc5e..c7af438a 100644 --- a/src/util/TokenStreamBase.js +++ b/src/util/TokenStreamBase.js @@ -63,14 +63,14 @@ function TokenStreamBase(input, tokenData){ */ TokenStreamBase.createTokenData = function(tokens){ - var nameMap = [], - typeMap = {}, - tokenData = tokens.concat([]), - i = 0, - len = tokenData.length+1; + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; tokenData.UNKNOWN = -1; - tokenData.unshift({name:"EOF"}); + tokenData.unshift({name:"EOF"}); for (; i < len; i++){ nameMap.push(tokenData[i].name); @@ -87,8 +87,8 @@ TokenStreamBase.createTokenData = function(tokens){ tokenData.type = function(c){ return typeMap[c]; }; - - return tokenData; + + return tokenData; }; TokenStreamBase.prototype = { @@ -149,6 +149,8 @@ TokenStreamBase.prototype = { */ mustMatch: function(tokenTypes, channel){ + var token; + //always convert to an array, makes things easier if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; @@ -225,7 +227,7 @@ TokenStreamBase.prototype = { } //call token retriever method - token = this._getToken(); + token = this._getToken(); //if it should be hidden, don't save a token if (token.type > -1 && !tokenInfo[token.type].hide){ From 750bad4f4d4b3495eb5151f123da6a3b5fece121 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 21 Sep 2011 12:20:18 -0700 Subject: [PATCH 003/313] Fixed error with parsing CSS comments --- build/node-parserlib.js | 6 +++--- build/parserlib-core.js | 2 +- build/parserlib-css.js | 4 ++-- build/parserlib.js | 6 +++--- src/css/TokenStream.js | 2 +- tests/css/CSSTokensTests.htm | 4 +++- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 16b47ee9..095f09e2 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -5152,7 +5152,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { comment += c; //look for end of comment - if (c == "*" && reader.peek() == "/"){ + if (comment.length > 2 && c == "*" && reader.peek() == "/"){ comment += reader.read(); break; } diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 9c7cf7a7..aabe969b 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index f33a9da0..3c53ea45 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -4246,7 +4246,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { comment += c; //look for end of comment - if (c == "*" && reader.peek() == "/"){ + if (comment.length > 2 && c == "*" && reader.peek() == "/"){ comment += reader.read(); break; } diff --git a/build/parserlib.js b/build/parserlib.js index ef7f9db7..bf167472 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:02:55 */ +/* Build time: 21-September-2011 12:19:58 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -5152,7 +5152,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { comment += c; //look for end of comment - if (c == "*" && reader.peek() == "/"){ + if (comment.length > 2 && c == "*" && reader.peek() == "/"){ comment += reader.read(); break; } diff --git a/src/css/TokenStream.js b/src/css/TokenStream.js index 8d06a929..300152b3 100755 --- a/src/css/TokenStream.js +++ b/src/css/TokenStream.js @@ -981,7 +981,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { comment += c; //look for end of comment - if (c == "*" && reader.peek() == "/"){ + if (comment.length > 2 && c == "*" && reader.peek() == "/"){ comment += reader.read(); break; } diff --git a/tests/css/CSSTokensTests.htm b/tests/css/CSSTokensTests.htm index 6f6aed3c..fb2eb18b 100755 --- a/tests/css/CSSTokensTests.htm +++ b/tests/css/CSSTokensTests.htm @@ -86,7 +86,9 @@

CSS Tokens Tests

patterns: { "/* booya */" : [], "/*\n booya */" : [], - "/*\n booya \n*/" : [] + "/*\n booya \n*/" : [], + "/*/*/" : [], + "/*/hello*/abc" : [CSSTokens.IDENT] } })); From e5bb0ecf605f840fa5e6ffea2408c11780b78f8a Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 21 Sep 2011 12:37:37 -0700 Subject: [PATCH 004/313] Fixed parsing of IE filters --- build/node-parserlib.js | 41 ++++++++++++++++++++++++++++++++---- build/parserlib-core.js | 2 +- build/parserlib-css.js | 39 +++++++++++++++++++++++++++++++--- build/parserlib.js | 41 ++++++++++++++++++++++++++++++++---- src/css/Parser.js | 37 ++++++++++++++++++++++++++++++-- tests/css/CSSParserTests.htm | 16 ++++++++++++++ tests/css/CSSTokensTests.htm | 6 +++--- 7 files changed, 165 insertions(+), 17 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 095f09e2..13a077ec 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2965,15 +2965,48 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, functionText = null, - expr = null; + expr = null, + lt; if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(); + functionText += expr; + + //START: Horrible hack in case it's an IE filter + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + //END: Horrible Hack tokenStream.match(Tokens.RPAREN); - functionText += expr + ")"; + functionText += ")"; this._readWhitespace(); } diff --git a/build/parserlib-core.js b/build/parserlib-core.js index aabe969b..4a7fb79b 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 3c53ea45..9704143e 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2059,15 +2059,48 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, functionText = null, - expr = null; + expr = null, + lt; if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(); + functionText += expr; + + //START: Horrible hack in case it's an IE filter + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + //END: Horrible Hack tokenStream.match(Tokens.RPAREN); - functionText += expr + ")"; + functionText += ")"; this._readWhitespace(); } diff --git a/build/parserlib.js b/build/parserlib.js index bf167472..514f2f1e 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:19:58 */ +/* Build time: 21-September-2011 12:37:16 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2965,15 +2965,48 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, functionText = null, - expr = null; + expr = null, + lt; if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(); + functionText += expr; + + //START: Horrible hack in case it's an IE filter + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + //END: Horrible Hack tokenStream.match(Tokens.RPAREN); - functionText += expr + ")"; + functionText += ")"; this._readWhitespace(); } diff --git a/src/css/Parser.js b/src/css/Parser.js index efae15e3..b778465e 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -1597,15 +1597,48 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, functionText = null, - expr = null; + expr = null, + lt; if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(); + functionText += expr; + + //START: Horrible hack in case it's an IE filter + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + //END: Horrible Hack tokenStream.match(Tokens.RPAREN); - functionText += expr + ")"; + functionText += ")"; this._readWhitespace(); } diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index bcfd5181..f3070741 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1201,6 +1201,12 @@

CSS Parser Tests

suite.add(new YAHOO.tool.TestCase({ name: "Special Cases", + + _should: { + error: { + testIEFilter5: "Unexpected token '=' at line 1, col 14." + } + }, testWithCommentAndSpaces: function(){ var parser = new Parser(); @@ -1279,8 +1285,18 @@

CSS Parser Tests

assert.isInstanceOf(parserlib.css.PropertyValue, result); assert.areEqual(1, result.parts.length); + assert.areEqual("alpha(opacity=10)", result.text); assert.areEqual("unknown", result.parts[0].type); + }, + + testIEFilter5: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("alpha(opacity=10)"); + + assert.isInstanceOf(parserlib.css.PropertyValue, result); } + + })); diff --git a/tests/css/CSSTokensTests.htm b/tests/css/CSSTokensTests.htm index fb2eb18b..c46af4b6 100755 --- a/tests/css/CSSTokensTests.htm +++ b/tests/css/CSSTokensTests.htm @@ -422,8 +422,8 @@

CSS Tokens Tests

//IE filters - not sure how to handle these yet "progid:DXImageTransform.Microsoft.Wave(strength=100)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN], - "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN], - "progid:DXImageTransform.Microsoft.Iris(irisstyle='STAR', duration=4)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.STRING, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN] + "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN], + "progid:DXImageTransform.Microsoft.Iris(irisstyle='STAR', duration=4)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.STRING, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN] } })); @@ -469,7 +469,7 @@

CSS Tokens Tests

"background: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], "background-color: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], - "filter: progid:DXImageTransform.Microsoft.Wave(strength=100);": [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN, CSSTokens.SEMICOLON] + "filter: progid:DXImageTransform.Microsoft.Wave(strength=100);": [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN, CSSTokens.SEMICOLON] } })); From ea730e80dd998314f810cca01cf5ee95525b5b38 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Sun, 25 Sep 2011 18:02:38 -0700 Subject: [PATCH 005/313] Added specificity calculation to parser --- build.xml | 1 + build/node-parserlib.js | 146 ++++++++++++++++++++++- build/parserlib-core.js | 2 +- build/parserlib-css.js | 144 ++++++++++++++++++++++- build/parserlib.js | 146 ++++++++++++++++++++++- src/css/Pseudos.js | 13 +++ src/css/Selector.js | 7 ++ src/css/Specificity.js | 120 +++++++++++++++++++ tests/css/CSSParserTests.htm | 20 +++- tests/css/CSSSpecificityTests.htm | 185 ++++++++++++++++++++++++++++++ 10 files changed, 777 insertions(+), 7 deletions(-) create mode 100644 src/css/Pseudos.js create mode 100644 src/css/Specificity.js create mode 100644 tests/css/CSSSpecificityTests.htm diff --git a/build.xml b/build.xml index adfd8fec..a7125b72 100644 --- a/build.xml +++ b/build.xml @@ -83,6 +83,7 @@ Selector :Selector, SelectorPart :SelectorPart, SelectorSubPart :SelectorSubPart, + Specificity :Specificity, TokenStream :TokenStream, Tokens :Tokens, ValidationError :ValidationError diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 13a077ec..2cac8e72 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -4096,6 +4096,19 @@ PropertyValuePart.prototype.constructor = PropertyValue; PropertyValuePart.fromToken = function(token){ return new PropertyValuePart(token.value, token.startLine, token.startCol); }; +var Pseudos = { + ":first-letter": 1, + ":first-line": 1, + ":before": 1, + ":after": 1 +}; + +Pseudos.ELEMENT = 1; +Pseudos.CLASS = 2; + +Pseudos.isElement = function(pseudo){ + return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; +}; /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -4117,6 +4130,13 @@ function Selector(parts, line, col){ * @property parts */ this.parts = parts; + + /** + * The specificity of the selector. + * @type parserlib.css.Specificity + * @property specificity + */ + this.specificity = Specificity.calculate(this); } @@ -4202,6 +4222,127 @@ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/** + * Represents a selector's specificity. + * @namespace parserlib.css + * @class Specificity + * @constructor + * @param {int} a Should be 1 for inline styles, zero for stylesheet styles + * @param {int} b Number of ID selectors + * @param {int} c Number of classes and pseudo classes + * @param {int} d Number of element names and pseudo elements + */ +function Specificity(a, b, c, d){ + this.a = a; + this.b = b; + this.c = c; + this.d = d; +} + +Specificity.prototype = { + constructor: Specificity, + + /** + * Compare this specificity to another. + * @param {Specificity} other The other specificity to compare to. + * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal. + * @method compare + */ + compare: function(other){ + var comps = ["a", "b", "c", "d"], + i, len; + + for (i=0, len=comps.length; i < len; i++){ + if (this[comps[i]] < other[comps[i]]){ + return -1; + } else if (this[comps[i]] > other[comps[i]]){ + return 1; + } + } + + return 0; + }, + + /** + * Creates a numeric value for the specificity. + * @return {int} The numeric value for the specificity. + * @method valueOf + */ + valueOf: function(){ + return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d; + }, + + /** + * Returns a string representation for specificity. + * @return {String} The string representation of specificity. + * @method toString + */ + toString: function(){ + return this.a + "," + this.b + "," + this.c + "," + this.d; + } + +}; + +/** + * Calculates the specificity of the given selector. + * @param {parserlib.css.Selector} The selector to calculate specificity for. + * @return {parserlib.css.Specificity} The specificity of the selector. + * @static + * @method calculate + */ +Specificity.calculate = function(selector){ + + var i, len, + b=0, c=0, d=0; + + function updateValues(part){ + + var i, j, len, num, + modifier; + + if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + d++; + } + + for (i=0, len=part.modifiers.length; i < len; i++){ + modifier = part.modifiers[i]; + switch(modifier.type){ + case "class": + case "attribute": + c++; + break; + + case "id": + b++; + break; + + case "pseudo": + if (Pseudos.isElement(modifier.text)){ + d++; + } else { + c++; + } + break; + + case "not": + for (j=0, num=modifier.args.length; j < num; j++){ + updateValues(modifier.args[j]); + } + } + } + } + + for (i=0, len=selector.parts.length; i < len; i++){ + part = selector.parts[i]; + + if (part instanceof SelectorPart){ + updateValues(part); + } + } + + return new Specificity(0, b, c, d); +}; + var h = /^[0-9a-fA-F]$/, @@ -5458,6 +5599,7 @@ MediaQuery :MediaQuery, Selector :Selector, SelectorPart :SelectorPart, SelectorSubPart :SelectorSubPart, +Specificity :Specificity, TokenStream :TokenStream, Tokens :Tokens, ValidationError :ValidationError diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 4a7fb79b..3fce550d 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 9704143e..e392866c 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3190,6 +3190,19 @@ PropertyValuePart.prototype.constructor = PropertyValue; PropertyValuePart.fromToken = function(token){ return new PropertyValuePart(token.value, token.startLine, token.startCol); }; +var Pseudos = { + ":first-letter": 1, + ":first-line": 1, + ":before": 1, + ":after": 1 +}; + +Pseudos.ELEMENT = 1; +Pseudos.CLASS = 2; + +Pseudos.isElement = function(pseudo){ + return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; +}; /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -3211,6 +3224,13 @@ function Selector(parts, line, col){ * @property parts */ this.parts = parts; + + /** + * The specificity of the selector. + * @type parserlib.css.Specificity + * @property specificity + */ + this.specificity = Specificity.calculate(this); } @@ -3296,6 +3316,127 @@ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/** + * Represents a selector's specificity. + * @namespace parserlib.css + * @class Specificity + * @constructor + * @param {int} a Should be 1 for inline styles, zero for stylesheet styles + * @param {int} b Number of ID selectors + * @param {int} c Number of classes and pseudo classes + * @param {int} d Number of element names and pseudo elements + */ +function Specificity(a, b, c, d){ + this.a = a; + this.b = b; + this.c = c; + this.d = d; +} + +Specificity.prototype = { + constructor: Specificity, + + /** + * Compare this specificity to another. + * @param {Specificity} other The other specificity to compare to. + * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal. + * @method compare + */ + compare: function(other){ + var comps = ["a", "b", "c", "d"], + i, len; + + for (i=0, len=comps.length; i < len; i++){ + if (this[comps[i]] < other[comps[i]]){ + return -1; + } else if (this[comps[i]] > other[comps[i]]){ + return 1; + } + } + + return 0; + }, + + /** + * Creates a numeric value for the specificity. + * @return {int} The numeric value for the specificity. + * @method valueOf + */ + valueOf: function(){ + return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d; + }, + + /** + * Returns a string representation for specificity. + * @return {String} The string representation of specificity. + * @method toString + */ + toString: function(){ + return this.a + "," + this.b + "," + this.c + "," + this.d; + } + +}; + +/** + * Calculates the specificity of the given selector. + * @param {parserlib.css.Selector} The selector to calculate specificity for. + * @return {parserlib.css.Specificity} The specificity of the selector. + * @static + * @method calculate + */ +Specificity.calculate = function(selector){ + + var i, len, + b=0, c=0, d=0; + + function updateValues(part){ + + var i, j, len, num, + modifier; + + if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + d++; + } + + for (i=0, len=part.modifiers.length; i < len; i++){ + modifier = part.modifiers[i]; + switch(modifier.type){ + case "class": + case "attribute": + c++; + break; + + case "id": + b++; + break; + + case "pseudo": + if (Pseudos.isElement(modifier.text)){ + d++; + } else { + c++; + } + break; + + case "not": + for (j=0, num=modifier.args.length; j < num; j++){ + updateValues(modifier.args[j]); + } + } + } + } + + for (i=0, len=selector.parts.length; i < len; i++){ + part = selector.parts[i]; + + if (part instanceof SelectorPart){ + updateValues(part); + } + } + + return new Specificity(0, b, c, d); +}; + var h = /^[0-9a-fA-F]$/, @@ -4552,6 +4693,7 @@ MediaQuery :MediaQuery, Selector :Selector, SelectorPart :SelectorPart, SelectorSubPart :SelectorSubPart, +Specificity :Specificity, TokenStream :TokenStream, Tokens :Tokens, ValidationError :ValidationError diff --git a/build/parserlib.js b/build/parserlib.js index 514f2f1e..176581e8 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-September-2011 12:37:16 */ +/* Build time: 25-September-2011 06:00:56 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -4096,6 +4096,19 @@ PropertyValuePart.prototype.constructor = PropertyValue; PropertyValuePart.fromToken = function(token){ return new PropertyValuePart(token.value, token.startLine, token.startCol); }; +var Pseudos = { + ":first-letter": 1, + ":first-line": 1, + ":before": 1, + ":after": 1 +}; + +Pseudos.ELEMENT = 1; +Pseudos.CLASS = 2; + +Pseudos.isElement = function(pseudo){ + return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; +}; /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -4117,6 +4130,13 @@ function Selector(parts, line, col){ * @property parts */ this.parts = parts; + + /** + * The specificity of the selector. + * @type parserlib.css.Specificity + * @property specificity + */ + this.specificity = Specificity.calculate(this); } @@ -4202,6 +4222,127 @@ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/** + * Represents a selector's specificity. + * @namespace parserlib.css + * @class Specificity + * @constructor + * @param {int} a Should be 1 for inline styles, zero for stylesheet styles + * @param {int} b Number of ID selectors + * @param {int} c Number of classes and pseudo classes + * @param {int} d Number of element names and pseudo elements + */ +function Specificity(a, b, c, d){ + this.a = a; + this.b = b; + this.c = c; + this.d = d; +} + +Specificity.prototype = { + constructor: Specificity, + + /** + * Compare this specificity to another. + * @param {Specificity} other The other specificity to compare to. + * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal. + * @method compare + */ + compare: function(other){ + var comps = ["a", "b", "c", "d"], + i, len; + + for (i=0, len=comps.length; i < len; i++){ + if (this[comps[i]] < other[comps[i]]){ + return -1; + } else if (this[comps[i]] > other[comps[i]]){ + return 1; + } + } + + return 0; + }, + + /** + * Creates a numeric value for the specificity. + * @return {int} The numeric value for the specificity. + * @method valueOf + */ + valueOf: function(){ + return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d; + }, + + /** + * Returns a string representation for specificity. + * @return {String} The string representation of specificity. + * @method toString + */ + toString: function(){ + return this.a + "," + this.b + "," + this.c + "," + this.d; + } + +}; + +/** + * Calculates the specificity of the given selector. + * @param {parserlib.css.Selector} The selector to calculate specificity for. + * @return {parserlib.css.Specificity} The specificity of the selector. + * @static + * @method calculate + */ +Specificity.calculate = function(selector){ + + var i, len, + b=0, c=0, d=0; + + function updateValues(part){ + + var i, j, len, num, + modifier; + + if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + d++; + } + + for (i=0, len=part.modifiers.length; i < len; i++){ + modifier = part.modifiers[i]; + switch(modifier.type){ + case "class": + case "attribute": + c++; + break; + + case "id": + b++; + break; + + case "pseudo": + if (Pseudos.isElement(modifier.text)){ + d++; + } else { + c++; + } + break; + + case "not": + for (j=0, num=modifier.args.length; j < num; j++){ + updateValues(modifier.args[j]); + } + } + } + } + + for (i=0, len=selector.parts.length; i < len; i++){ + part = selector.parts[i]; + + if (part instanceof SelectorPart){ + updateValues(part); + } + } + + return new Specificity(0, b, c, d); +}; + var h = /^[0-9a-fA-F]$/, @@ -5458,6 +5599,7 @@ MediaQuery :MediaQuery, Selector :Selector, SelectorPart :SelectorPart, SelectorSubPart :SelectorSubPart, +Specificity :Specificity, TokenStream :TokenStream, Tokens :Tokens, ValidationError :ValidationError diff --git a/src/css/Pseudos.js b/src/css/Pseudos.js new file mode 100644 index 00000000..911a66a0 --- /dev/null +++ b/src/css/Pseudos.js @@ -0,0 +1,13 @@ +var Pseudos = { + ":first-letter": 1, + ":first-line": 1, + ":before": 1, + ":after": 1 +}; + +Pseudos.ELEMENT = 1; +Pseudos.CLASS = 2; + +Pseudos.isElement = function(pseudo){ + return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; +}; \ No newline at end of file diff --git a/src/css/Selector.js b/src/css/Selector.js index 0d6b6a06..331d09cd 100644 --- a/src/css/Selector.js +++ b/src/css/Selector.js @@ -19,6 +19,13 @@ function Selector(parts, line, col){ * @property parts */ this.parts = parts; + + /** + * The specificity of the selector. + * @type parserlib.css.Specificity + * @property specificity + */ + this.specificity = Specificity.calculate(this); } diff --git a/src/css/Specificity.js b/src/css/Specificity.js new file mode 100644 index 00000000..0dbca2bd --- /dev/null +++ b/src/css/Specificity.js @@ -0,0 +1,120 @@ +/** + * Represents a selector's specificity. + * @namespace parserlib.css + * @class Specificity + * @constructor + * @param {int} a Should be 1 for inline styles, zero for stylesheet styles + * @param {int} b Number of ID selectors + * @param {int} c Number of classes and pseudo classes + * @param {int} d Number of element names and pseudo elements + */ +function Specificity(a, b, c, d){ + this.a = a; + this.b = b; + this.c = c; + this.d = d; +} + +Specificity.prototype = { + constructor: Specificity, + + /** + * Compare this specificity to another. + * @param {Specificity} other The other specificity to compare to. + * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal. + * @method compare + */ + compare: function(other){ + var comps = ["a", "b", "c", "d"], + i, len; + + for (i=0, len=comps.length; i < len; i++){ + if (this[comps[i]] < other[comps[i]]){ + return -1; + } else if (this[comps[i]] > other[comps[i]]){ + return 1; + } + } + + return 0; + }, + + /** + * Creates a numeric value for the specificity. + * @return {int} The numeric value for the specificity. + * @method valueOf + */ + valueOf: function(){ + return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d; + }, + + /** + * Returns a string representation for specificity. + * @return {String} The string representation of specificity. + * @method toString + */ + toString: function(){ + return this.a + "," + this.b + "," + this.c + "," + this.d; + } + +}; + +/** + * Calculates the specificity of the given selector. + * @param {parserlib.css.Selector} The selector to calculate specificity for. + * @return {parserlib.css.Specificity} The specificity of the selector. + * @static + * @method calculate + */ +Specificity.calculate = function(selector){ + + var i, len, + b=0, c=0, d=0; + + function updateValues(part){ + + var i, j, len, num, + modifier; + + if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + d++; + } + + for (i=0, len=part.modifiers.length; i < len; i++){ + modifier = part.modifiers[i]; + switch(modifier.type){ + case "class": + case "attribute": + c++; + break; + + case "id": + b++; + break; + + case "pseudo": + if (Pseudos.isElement(modifier.text)){ + d++; + } else { + c++; + } + break; + + case "not": + for (j=0, num=modifier.args.length; j < num; j++){ + updateValues(modifier.args[j]); + } + } + } + } + + for (i=0, len=selector.parts.length; i < len; i++){ + part = selector.parts[i]; + + if (part instanceof SelectorPart){ + updateValues(part); + } + } + + return new Specificity(0, b, c, d); +}; diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index f3070741..d9a4afb8 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -48,6 +48,7 @@

CSS Parser Tests

assert.areEqual(Parser.SELECTOR_PART_TYPE, result.parts[0].type); assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + assert.areEqual(1, result.specificity.valueOf()); }, testSimpleTypeSelectorPlusNamespace: function(){ @@ -62,6 +63,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("svg|rect", result.parts[0].elementName, "Element name should be 'svg|rect'."); assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + assert.areEqual(1, result.specificity.valueOf()); }, testSimpleTypeSelectorPlusBlankNamespace: function(){ @@ -75,6 +77,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("|rect", result.parts[0].elementName, "Element name should be '|rect'."); assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + assert.areEqual(1, result.specificity.valueOf()); }, testSimpleTypeSelectorPlusUniversalNamespace: function(){ @@ -88,6 +91,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("*|rect", result.parts[0].elementName, "Element name should be '*|rect'."); assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + assert.areEqual(1, result.specificity.valueOf()); } })); @@ -106,6 +110,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("*", result.parts[0].elementName, "Element name should be '*'."); assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + assert.areEqual(0, result.specificity.valueOf()); }, testSimpleUniversalSelectorPlusNamespace: function(){ @@ -119,6 +124,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("svg|*", result.parts[0].elementName, "Element name should be 'svg|*'."); assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + assert.areEqual(0, result.specificity.valueOf()); }, testSimpleUniversalSelectorPlusBlankNamespace: function(){ @@ -132,6 +138,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("|*", result.parts[0].elementName, "Element name should be '|*'."); assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + assert.areEqual(0, result.specificity.valueOf()); }, testSimpleUniversalSelectorPlusUniversalNamespace: function(){ @@ -145,6 +152,7 @@

CSS Parser Tests

assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); assert.areEqual("*|*", result.parts[0].elementName, "Element name should be '*|*'."); assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + assert.areEqual(0, result.specificity.valueOf()); } })); @@ -168,6 +176,7 @@

CSS Parser Tests

assert.areEqual("[class]", result.parts[0].modifiers[0].text, "Modifier text should be '[class]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -184,7 +193,7 @@

CSS Parser Tests

assert.areEqual("[class=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=\"selected\"]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); - + assert.areEqual(11, result.specificity.valueOf()); }, testAttributeEquivalenceSelectorNoString: function(){ @@ -200,6 +209,7 @@

CSS Parser Tests

assert.areEqual("[class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=selected]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -216,6 +226,7 @@

CSS Parser Tests

assert.areEqual("[class~=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class~=\"selected\"]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -232,6 +243,7 @@

CSS Parser Tests

assert.areEqual("[class|=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class|=\"selected\"]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -248,6 +260,7 @@

CSS Parser Tests

assert.areEqual("[type^=\"image/\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[type^=\"image/\"]'."); assert.areEqual(7, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, testAttributeEndMatchSelector: function(){ @@ -263,6 +276,7 @@

CSS Parser Tests

assert.areEqual("[href$=\".html\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[href$=\".html\"]'."); assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, testAttributeContainsMatchSelector: function(){ @@ -278,6 +292,7 @@

CSS Parser Tests

assert.areEqual("[title*=\"hello\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[title*=\"hello\"]'."); assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, testAttributeEquivalenceSelectorNamespace: function(){ @@ -293,6 +308,7 @@

CSS Parser Tests

assert.areEqual("[html|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[html|class=selected]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -309,6 +325,7 @@

CSS Parser Tests

assert.areEqual("[*|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[*|class=selected]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); }, @@ -325,6 +342,7 @@

CSS Parser Tests

assert.areEqual("[|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[|class=selected]'."); assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + assert.areEqual(11, result.specificity.valueOf()); } })); diff --git a/tests/css/CSSSpecificityTests.htm b/tests/css/CSSSpecificityTests.htm new file mode 100644 index 00000000..4753b913 --- /dev/null +++ b/tests/css/CSSSpecificityTests.htm @@ -0,0 +1,185 @@ + + + +CSS Specificity Tests + + + + + + + + + +

CSS Specificity Tests

+ + + From 760cafbea68c0f42812f9469232e7d76d74492ce Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 26 Sep 2011 17:00:56 -0700 Subject: [PATCH 006/313] Added instance constants to Parser for easier use --- build/node-parserlib.js | 18 +++++++++++++++--- build/parserlib-core.js | 2 +- build/parserlib-css.js | 16 ++++++++++++++-- build/parserlib.js | 18 +++++++++++++++--- src/css/Parser.js | 14 +++++++++++++- 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 2cac8e72..f588cae9 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1389,6 +1389,7 @@ function Parser(options){ this._tokenStream = null; } +//Static constants Parser.DEFAULT_TYPE = 0; Parser.COMBINATOR_TYPE = 1; Parser.MEDIA_FEATURE_TYPE = 2; @@ -1400,7 +1401,6 @@ Parser.SELECTOR_TYPE = 7; Parser.SELECTOR_PART_TYPE = 8; Parser.SELECTOR_SUB_PART_TYPE = 9; - Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -1409,6 +1409,18 @@ Parser.prototype = function(){ //restore constructor constructor: Parser, + + //instance constants - yuck + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, //----------------------------------------------------------------- // Grammar diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 3fce550d..bf2b386e 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index e392866c..3ecf9b47 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -483,6 +483,7 @@ function Parser(options){ this._tokenStream = null; } +//Static constants Parser.DEFAULT_TYPE = 0; Parser.COMBINATOR_TYPE = 1; Parser.MEDIA_FEATURE_TYPE = 2; @@ -494,7 +495,6 @@ Parser.SELECTOR_TYPE = 7; Parser.SELECTOR_PART_TYPE = 8; Parser.SELECTOR_SUB_PART_TYPE = 9; - Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -503,6 +503,18 @@ Parser.prototype = function(){ //restore constructor constructor: Parser, + + //instance constants - yuck + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, //----------------------------------------------------------------- // Grammar diff --git a/build/parserlib.js b/build/parserlib.js index 176581e8..f9de4934 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ var parserlib = {}; (function(){ @@ -927,7 +927,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-September-2011 06:00:56 */ +/* Build time: 26-September-2011 05:00:33 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1389,6 +1389,7 @@ function Parser(options){ this._tokenStream = null; } +//Static constants Parser.DEFAULT_TYPE = 0; Parser.COMBINATOR_TYPE = 1; Parser.MEDIA_FEATURE_TYPE = 2; @@ -1400,7 +1401,6 @@ Parser.SELECTOR_TYPE = 7; Parser.SELECTOR_PART_TYPE = 8; Parser.SELECTOR_SUB_PART_TYPE = 9; - Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -1409,6 +1409,18 @@ Parser.prototype = function(){ //restore constructor constructor: Parser, + + //instance constants - yuck + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, //----------------------------------------------------------------- // Grammar diff --git a/src/css/Parser.js b/src/css/Parser.js index b778465e..264ecb8c 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -21,6 +21,7 @@ function Parser(options){ this._tokenStream = null; } +//Static constants Parser.DEFAULT_TYPE = 0; Parser.COMBINATOR_TYPE = 1; Parser.MEDIA_FEATURE_TYPE = 2; @@ -32,7 +33,6 @@ Parser.SELECTOR_TYPE = 7; Parser.SELECTOR_PART_TYPE = 8; Parser.SELECTOR_SUB_PART_TYPE = 9; - Parser.prototype = function(){ var proto = new EventTarget(), //new prototype @@ -41,6 +41,18 @@ Parser.prototype = function(){ //restore constructor constructor: Parser, + + //instance constants - yuck + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, //----------------------------------------------------------------- // Grammar From d2fa0a32c707a18c55bb55728d478e89099ebe30 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 19 Oct 2011 16:46:40 -0700 Subject: [PATCH 007/313] Beginnings of CSS validation --- build/node-parserlib.js | 401 +++++++++++++++++++++++------------ build/parserlib-core.js | 5 +- build/parserlib-css.js | 394 +++++++++++++++++++++++----------- build/parserlib.js | 399 ++++++++++++++++++++++------------ src/css/Parser.js | 28 +-- src/css/Properties.js | 363 ++++++++++++++++++++++--------- tests/css/CSSParserTests.htm | 207 ++++++++++++++++++ 7 files changed, 1278 insertions(+), 519 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index f588cae9..d0a9ecbf 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,10 +21,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ var parserlib = {}; (function(){ + /** * A generic base to inherit from for any object * that needs event handling. @@ -895,6 +896,7 @@ TokenStreamBase.prototype = { + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -904,6 +906,7 @@ TokenStreamBase : TokenStreamBase }; })(); + /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -927,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -935,6 +938,7 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; + var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -2774,7 +2778,7 @@ Parser.prototype = function(){ expr = null, prio = null, error = null, - valid = true; + invalid = null; property = this._property(); if (property !== null){ @@ -2794,8 +2798,7 @@ Parser.prototype = function(){ try { this._validateProperty(property, expr); } catch (ex) { - valid = false; - error = ex; + invalid = ex; } this.fire({ @@ -2805,8 +2808,7 @@ Parser.prototype = function(){ important: prio, line: property.line, col: property.col, - valid: valid, - error: error + invalid: invalid }); return true; @@ -3418,25 +3420,7 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - validation = Properties[name]; - if (typeof validation == "object"){ - for (i=0, len=validation.parts.length; i < len; i++){ - if (!validation.parts[i]){ - throw new ValidationError("Unexpected value. Expected only " + validation.parts.length + " values for property '" + property + "'.", - value.line, value.col); - } else if ((new RegExp("^("+validation.parts[i].types.join("|")+")$")).test(value.parts[i].type)){ - if (validation.parts[i][RegExp.$1]){ - if (!validation.parts[i][RegExp.$1].test(value.parts[i])){ - throw new ValidationError("Unexpected value '" + value.parts[i] + - "'.", value.parts[i].line, value.parts[i].col); - } - } - } else { - throw new ValidationError("Unexpected value type " + value.parts[i].type + - ". Expected " + validation.parts[i].types + ".", value.parts[i].line, value.parts[i].col); - } - } - } + Properties[name](value); //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok @@ -3561,24 +3545,129 @@ nth ; */ var Validation = { - measurement: { - parts: [ - { - types: ["length", "percentage", "integer", "identifier"], - identifier: /^(auto|inherit)$/i, - integer: /^0$/ - } - ] + + isColor: function(part, other){ + var text = part.text.toString().toLowerCase(), + pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; + + if (part.type != "color"){ + if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ + return false; + } + } + + return true; + }, + + isIdentifier: function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(","), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + isLength: function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + isInteger: function(part){ + return part.type == "integer"; + }, + + isPercentage: function(part){ + return part.type == "percentage" || part == "0"; + }, + + isMeasurement: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + }, + + isBorderWidth: function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + }, + + isBorderStyle: function(part){ + return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + }, + + isBorderSideRadius: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part); + }, + + oneValue: function(value){ + var parts = value.parts; + if (parts.length != 1){ + throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); + } + }, + + maxValues: function(value, max){ + var parts = value.parts; + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); + } + }, + + oneColor: function(value, other){ + var part = value.parts[0], + text = part.text.toString().toLowerCase(); + + Validation.oneValue(value); + + if (!Validation.isColor(part, other)){ + throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); + } + }, + + oneColorOrTransparent: function(value){ + Validation.oneColor(value, "transparent"); }, - oneColor: { - maxParts: 1, - minParts: 1, - parts: [ - { - types: ["color", "identifier"], - identifier: /^(inherit|transparent)$/i - } - ] + + oneIdentifier: function(value, options){ + + Validation.oneValue(value); + + if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ + throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); + } + }, + + oneMeasurement: function(value){ + Validation.oneValue(value); + if (!Validation.isMeasurement(value.parts[0])){ + throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderWidth: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderWidth(value.parts[0])){ + throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderStyle: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderStyle(value.parts[0])){ + throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderSideRadius: function(value){ + Validation.maxValues(value, 2); + for (var i=0, len= value.parts.length; i < len; i++){ + if (!Validation.isBorderSideRadius(value.parts[i])){ + throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); + } + } } }; @@ -3607,10 +3696,12 @@ var Properties = { "azimuth": 1, "backface-visibility": 1, "background": 1, - "background-attachment": 1, + "background-attachment": function(value){ + Validation.oneIdentifier(value, "scroll,fixed,inherit"); + }, "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColor, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, @@ -3626,12 +3717,14 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": 1, - "border-bottom-right-radius": 1, - "border-bottom-style": 1, - "border-bottom-width": 1, - "border-collapse": 1, - "border-color": Validation.oneColor, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": function(value){ + Validation.oneIdentifier(value, "collapse,separate,inherit"); + }, + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -3639,26 +3732,42 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": 1, - "border-left-style": 1, - "border-left-width": 1, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": 1, - "border-right-style": 1, - "border-right-width": 1, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, - "border-style": 1, + "border-style": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderStyle(value.parts[i])){ + throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, "border-top": 1, - "border-top-color": 1, - "border-top-left-radius": 1, - "border-top-right-radius": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "bottom": Validation.measurement, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, + "border-width": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderWidth(value.parts[i])){ + throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": 1, + "box-decoration-break": function(value){ + Validation.oneIdentifier(value, "slice,clone"); + }, "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -3671,17 +3780,14 @@ var Properties = { "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": { - parts: [ - { - types: ["color", "identifier"], - identifier: /^inherit$/i - } - ] + "caption-side": function(value){ + Validation.oneIdentifier(value, "top,bottom,inherit"); }, + "clear": function(value){ + Validation.oneIdentifier(value, "none,right,left,both,inherit"); + }, + "clip": 1, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -3697,11 +3803,15 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": 1, + "cue": function(value){ + Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); + }, "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": 1, + "direction": function(value){ + Validation.oneIdentifier(value, "ltr,rtl,inherit"); + }, "display": 1, "dominant-baseline": 1, "drop-initial-after-adjust": 1, @@ -3711,16 +3821,13 @@ var Properties = { "drop-initial-size": 1, "drop-initial-value": 1, "elevation": 1, - "empty-cells": 1, + "empty-cells": function(value){ + Validation.oneIdentifier(value, "show,hide,inherit"); + }, "fit": 1, "fit-position": 1, - "float": { - parts: [ - { - types: ["identifier"], - identifier: /^(left|right|none|inherit)$/i - } - ] + "float": function(value){ + Validation.oneIdentifier(value, "left,right,none,inherit"); }, "float-offset": 1, @@ -3729,13 +3836,17 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": 1, - "font-variant": 1, + "font-style": function(value){ + Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); + }, + "font-variant": function(value){ + Validation.oneIdentifier(value, "normal,small-caps,inherit"); + }, "font-weight": 1, "grid-columns": 1, "grid-rows": 1, "hanging-punctuation": 1, - "height": Validation.measurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -3747,7 +3858,7 @@ var Properties = { "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.measurement, + "left": Validation.oneMeasurement, "letter-spacing": 1, "line-height": 1, "line-stacking": 1, @@ -3756,8 +3867,12 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, + "list-style-position": function(value){ + Validation.oneIdentifier(value, "inside,outsider,inherit"); + }, + "list-style-type": function(value){ + Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); + }, "margin": 1, "margin-bottom": 1, "margin-left": 1, @@ -3784,11 +3899,15 @@ var Properties = { "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": 1, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": 1, + "overflow": function(value){ + Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); + }, "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, @@ -3798,9 +3917,15 @@ var Properties = { "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, + "page-break-after": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-before": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-inside": function(value){ + Validation.oneIdentifier(value, "auto,avoid,inherit"); + }, "page-policy": 1, "pause": 1, "pause-after": 1, @@ -3811,7 +3936,9 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": 1, + "position": function(value){ + Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); + }, "presentation-level": 1, "punctuation-trim": 1, "quotes": 1, @@ -3821,7 +3948,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.measurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -3829,10 +3956,18 @@ var Properties = { "ruby-position": 1, "ruby-span": 1, "size": 1, - "speak": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, + "speak": function(value){ + Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); + }, + "speak-header": function(value){ + Validation.oneIdentifier(value, "once,always,inherit"); + }, + "speak-numeral": function(value){ + Validation.oneIdentifier(value, "digits,continuous,inherit"); + }, + "speak-punctuation": function(value){ + Validation.oneIdentifier(value, "code,none,inherit"); + }, "speech-rate": 1, "stress": 1, "string-set": 1, @@ -3841,7 +3976,9 @@ var Properties = { "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": 1, + "text-align": function(value){ + Validation.oneIdentifier(value, "left,right,center,justify,inherit"); + }, "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -3850,9 +3987,11 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": 1, + "text-transform": function(value){ + Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); + }, "text-wrap": 1, - "top": Validation.measurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -3861,11 +4000,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": 1, + "unicode-bidi": function(value){ + Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); + }, "user-modify": 1, "user-select": 1, "vertical-align": 1, - "visibility": 1, + "visibility": function(value){ + Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); + }, "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -3875,32 +4018,26 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": 1, + "white-space": function(value){ + Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); + }, "white-space-collapse": 1, "widows": 1, - "width": Validation.measurement, + "width": Validation.oneMeasurement, "word-break": 1, - "word-spacing": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "number", "identifier"], - identifier: /^(normal|inherit)$/, - number: /^0$/ - } - ] - }, + "word-spacing": function(value){ + Validation.oneValue(value); + if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ + throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); + } + }, + "word-wrap": 1, - "z-index": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "identifier"], - identifier: /^(auto|inherit)$/ - } - ] + "z-index": function(value){ + Validation.oneValue(value); + if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ + throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); + } } @@ -5599,6 +5736,7 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); + parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -5619,8 +5757,11 @@ ValidationError :ValidationError })(); + + (function(){ for(var prop in parserlib){ exports[prop] = parserlib[prop]; } })(); + diff --git a/build/parserlib-core.js b/build/parserlib-core.js index bf2b386e..4993725d 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,10 +21,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ var parserlib = {}; (function(){ + /** * A generic base to inherit from for any object * that needs event handling. @@ -895,6 +896,7 @@ TokenStreamBase.prototype = { + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -903,3 +905,4 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); + diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 3ecf9b47..a2380bb4 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -29,6 +29,7 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; + var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -1868,7 +1869,7 @@ Parser.prototype = function(){ expr = null, prio = null, error = null, - valid = true; + invalid = null; property = this._property(); if (property !== null){ @@ -1888,8 +1889,7 @@ Parser.prototype = function(){ try { this._validateProperty(property, expr); } catch (ex) { - valid = false; - error = ex; + invalid = ex; } this.fire({ @@ -1899,8 +1899,7 @@ Parser.prototype = function(){ important: prio, line: property.line, col: property.col, - valid: valid, - error: error + invalid: invalid }); return true; @@ -2512,25 +2511,7 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - validation = Properties[name]; - if (typeof validation == "object"){ - for (i=0, len=validation.parts.length; i < len; i++){ - if (!validation.parts[i]){ - throw new ValidationError("Unexpected value. Expected only " + validation.parts.length + " values for property '" + property + "'.", - value.line, value.col); - } else if ((new RegExp("^("+validation.parts[i].types.join("|")+")$")).test(value.parts[i].type)){ - if (validation.parts[i][RegExp.$1]){ - if (!validation.parts[i][RegExp.$1].test(value.parts[i])){ - throw new ValidationError("Unexpected value '" + value.parts[i] + - "'.", value.parts[i].line, value.parts[i].col); - } - } - } else { - throw new ValidationError("Unexpected value type " + value.parts[i].type + - ". Expected " + validation.parts[i].types + ".", value.parts[i].line, value.parts[i].col); - } - } - } + Properties[name](value); //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok @@ -2655,24 +2636,129 @@ nth ; */ var Validation = { - measurement: { - parts: [ - { - types: ["length", "percentage", "integer", "identifier"], - identifier: /^(auto|inherit)$/i, - integer: /^0$/ - } - ] + + isColor: function(part, other){ + var text = part.text.toString().toLowerCase(), + pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; + + if (part.type != "color"){ + if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ + return false; + } + } + + return true; + }, + + isIdentifier: function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(","), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; }, - oneColor: { - maxParts: 1, - minParts: 1, - parts: [ - { - types: ["color", "identifier"], - identifier: /^(inherit|transparent)$/i - } - ] + + isLength: function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + isInteger: function(part){ + return part.type == "integer"; + }, + + isPercentage: function(part){ + return part.type == "percentage" || part == "0"; + }, + + isMeasurement: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + }, + + isBorderWidth: function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + }, + + isBorderStyle: function(part){ + return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + }, + + isBorderSideRadius: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part); + }, + + oneValue: function(value){ + var parts = value.parts; + if (parts.length != 1){ + throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); + } + }, + + maxValues: function(value, max){ + var parts = value.parts; + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); + } + }, + + oneColor: function(value, other){ + var part = value.parts[0], + text = part.text.toString().toLowerCase(); + + Validation.oneValue(value); + + if (!Validation.isColor(part, other)){ + throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); + } + }, + + oneColorOrTransparent: function(value){ + Validation.oneColor(value, "transparent"); + }, + + oneIdentifier: function(value, options){ + + Validation.oneValue(value); + + if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ + throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); + } + }, + + oneMeasurement: function(value){ + Validation.oneValue(value); + if (!Validation.isMeasurement(value.parts[0])){ + throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderWidth: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderWidth(value.parts[0])){ + throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderStyle: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderStyle(value.parts[0])){ + throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderSideRadius: function(value){ + Validation.maxValues(value, 2); + for (var i=0, len= value.parts.length; i < len; i++){ + if (!Validation.isBorderSideRadius(value.parts[i])){ + throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); + } + } } }; @@ -2701,10 +2787,12 @@ var Properties = { "azimuth": 1, "backface-visibility": 1, "background": 1, - "background-attachment": 1, + "background-attachment": function(value){ + Validation.oneIdentifier(value, "scroll,fixed,inherit"); + }, "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColor, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, @@ -2720,12 +2808,14 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": 1, - "border-bottom-right-radius": 1, - "border-bottom-style": 1, - "border-bottom-width": 1, - "border-collapse": 1, - "border-color": Validation.oneColor, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": function(value){ + Validation.oneIdentifier(value, "collapse,separate,inherit"); + }, + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -2733,26 +2823,42 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": 1, - "border-left-style": 1, - "border-left-width": 1, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": 1, - "border-right-style": 1, - "border-right-width": 1, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, - "border-style": 1, + "border-style": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderStyle(value.parts[i])){ + throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, "border-top": 1, - "border-top-color": 1, - "border-top-left-radius": 1, - "border-top-right-radius": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "bottom": Validation.measurement, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, + "border-width": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderWidth(value.parts[i])){ + throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": 1, + "box-decoration-break": function(value){ + Validation.oneIdentifier(value, "slice,clone"); + }, "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -2765,17 +2871,14 @@ var Properties = { "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": { - parts: [ - { - types: ["color", "identifier"], - identifier: /^inherit$/i - } - ] + "caption-side": function(value){ + Validation.oneIdentifier(value, "top,bottom,inherit"); + }, + "clear": function(value){ + Validation.oneIdentifier(value, "none,right,left,both,inherit"); }, + "clip": 1, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -2791,11 +2894,15 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": 1, + "cue": function(value){ + Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); + }, "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": 1, + "direction": function(value){ + Validation.oneIdentifier(value, "ltr,rtl,inherit"); + }, "display": 1, "dominant-baseline": 1, "drop-initial-after-adjust": 1, @@ -2805,16 +2912,13 @@ var Properties = { "drop-initial-size": 1, "drop-initial-value": 1, "elevation": 1, - "empty-cells": 1, + "empty-cells": function(value){ + Validation.oneIdentifier(value, "show,hide,inherit"); + }, "fit": 1, "fit-position": 1, - "float": { - parts: [ - { - types: ["identifier"], - identifier: /^(left|right|none|inherit)$/i - } - ] + "float": function(value){ + Validation.oneIdentifier(value, "left,right,none,inherit"); }, "float-offset": 1, @@ -2823,13 +2927,17 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": 1, - "font-variant": 1, + "font-style": function(value){ + Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); + }, + "font-variant": function(value){ + Validation.oneIdentifier(value, "normal,small-caps,inherit"); + }, "font-weight": 1, "grid-columns": 1, "grid-rows": 1, "hanging-punctuation": 1, - "height": Validation.measurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -2841,7 +2949,7 @@ var Properties = { "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.measurement, + "left": Validation.oneMeasurement, "letter-spacing": 1, "line-height": 1, "line-stacking": 1, @@ -2850,8 +2958,12 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, + "list-style-position": function(value){ + Validation.oneIdentifier(value, "inside,outsider,inherit"); + }, + "list-style-type": function(value){ + Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); + }, "margin": 1, "margin-bottom": 1, "margin-left": 1, @@ -2878,11 +2990,15 @@ var Properties = { "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": 1, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": 1, + "overflow": function(value){ + Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); + }, "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, @@ -2892,9 +3008,15 @@ var Properties = { "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, + "page-break-after": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-before": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-inside": function(value){ + Validation.oneIdentifier(value, "auto,avoid,inherit"); + }, "page-policy": 1, "pause": 1, "pause-after": 1, @@ -2905,7 +3027,9 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": 1, + "position": function(value){ + Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); + }, "presentation-level": 1, "punctuation-trim": 1, "quotes": 1, @@ -2915,7 +3039,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.measurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -2923,10 +3047,18 @@ var Properties = { "ruby-position": 1, "ruby-span": 1, "size": 1, - "speak": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, + "speak": function(value){ + Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); + }, + "speak-header": function(value){ + Validation.oneIdentifier(value, "once,always,inherit"); + }, + "speak-numeral": function(value){ + Validation.oneIdentifier(value, "digits,continuous,inherit"); + }, + "speak-punctuation": function(value){ + Validation.oneIdentifier(value, "code,none,inherit"); + }, "speech-rate": 1, "stress": 1, "string-set": 1, @@ -2935,7 +3067,9 @@ var Properties = { "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": 1, + "text-align": function(value){ + Validation.oneIdentifier(value, "left,right,center,justify,inherit"); + }, "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -2944,9 +3078,11 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": 1, + "text-transform": function(value){ + Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); + }, "text-wrap": 1, - "top": Validation.measurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -2955,11 +3091,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": 1, + "unicode-bidi": function(value){ + Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); + }, "user-modify": 1, "user-select": 1, "vertical-align": 1, - "visibility": 1, + "visibility": function(value){ + Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); + }, "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -2969,32 +3109,26 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": 1, + "white-space": function(value){ + Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); + }, "white-space-collapse": 1, "widows": 1, - "width": Validation.measurement, + "width": Validation.oneMeasurement, "word-break": 1, - "word-spacing": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "number", "identifier"], - identifier: /^(normal|inherit)$/, - number: /^0$/ - } - ] - }, + "word-spacing": function(value){ + Validation.oneValue(value); + if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ + throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); + } + }, + "word-wrap": 1, - "z-index": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "identifier"], - identifier: /^(auto|inherit)$/ - } - ] + "z-index": function(value){ + Validation.oneValue(value); + if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ + throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); + } } @@ -4693,6 +4827,7 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); + parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -4711,3 +4846,4 @@ Tokens :Tokens, ValidationError :ValidationError }; })(); + diff --git a/build/parserlib.js b/build/parserlib.js index f9de4934..c4493d42 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,10 +21,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ var parserlib = {}; (function(){ + /** * A generic base to inherit from for any object * that needs event handling. @@ -895,6 +896,7 @@ TokenStreamBase.prototype = { + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -904,6 +906,7 @@ TokenStreamBase : TokenStreamBase }; })(); + /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -927,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 26-September-2011 05:00:33 */ +/* Build time: 19-October-2011 04:46:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -935,6 +938,7 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; + var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -2774,7 +2778,7 @@ Parser.prototype = function(){ expr = null, prio = null, error = null, - valid = true; + invalid = null; property = this._property(); if (property !== null){ @@ -2794,8 +2798,7 @@ Parser.prototype = function(){ try { this._validateProperty(property, expr); } catch (ex) { - valid = false; - error = ex; + invalid = ex; } this.fire({ @@ -2805,8 +2808,7 @@ Parser.prototype = function(){ important: prio, line: property.line, col: property.col, - valid: valid, - error: error + invalid: invalid }); return true; @@ -3418,25 +3420,7 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - validation = Properties[name]; - if (typeof validation == "object"){ - for (i=0, len=validation.parts.length; i < len; i++){ - if (!validation.parts[i]){ - throw new ValidationError("Unexpected value. Expected only " + validation.parts.length + " values for property '" + property + "'.", - value.line, value.col); - } else if ((new RegExp("^("+validation.parts[i].types.join("|")+")$")).test(value.parts[i].type)){ - if (validation.parts[i][RegExp.$1]){ - if (!validation.parts[i][RegExp.$1].test(value.parts[i])){ - throw new ValidationError("Unexpected value '" + value.parts[i] + - "'.", value.parts[i].line, value.parts[i].col); - } - } - } else { - throw new ValidationError("Unexpected value type " + value.parts[i].type + - ". Expected " + validation.parts[i].types + ".", value.parts[i].line, value.parts[i].col); - } - } - } + Properties[name](value); //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok @@ -3561,24 +3545,129 @@ nth ; */ var Validation = { - measurement: { - parts: [ - { - types: ["length", "percentage", "integer", "identifier"], - identifier: /^(auto|inherit)$/i, - integer: /^0$/ - } - ] + + isColor: function(part, other){ + var text = part.text.toString().toLowerCase(), + pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; + + if (part.type != "color"){ + if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ + return false; + } + } + + return true; }, - oneColor: { - maxParts: 1, - minParts: 1, - parts: [ - { - types: ["color", "identifier"], - identifier: /^(inherit|transparent)$/i - } - ] + + isIdentifier: function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(","), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + isLength: function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + isInteger: function(part){ + return part.type == "integer"; + }, + + isPercentage: function(part){ + return part.type == "percentage" || part == "0"; + }, + + isMeasurement: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + }, + + isBorderWidth: function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + }, + + isBorderStyle: function(part){ + return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + }, + + isBorderSideRadius: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part); + }, + + oneValue: function(value){ + var parts = value.parts; + if (parts.length != 1){ + throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); + } + }, + + maxValues: function(value, max){ + var parts = value.parts; + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); + } + }, + + oneColor: function(value, other){ + var part = value.parts[0], + text = part.text.toString().toLowerCase(); + + Validation.oneValue(value); + + if (!Validation.isColor(part, other)){ + throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); + } + }, + + oneColorOrTransparent: function(value){ + Validation.oneColor(value, "transparent"); + }, + + oneIdentifier: function(value, options){ + + Validation.oneValue(value); + + if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ + throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); + } + }, + + oneMeasurement: function(value){ + Validation.oneValue(value); + if (!Validation.isMeasurement(value.parts[0])){ + throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderWidth: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderWidth(value.parts[0])){ + throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderStyle: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderStyle(value.parts[0])){ + throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderSideRadius: function(value){ + Validation.maxValues(value, 2); + for (var i=0, len= value.parts.length; i < len; i++){ + if (!Validation.isBorderSideRadius(value.parts[i])){ + throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); + } + } } }; @@ -3607,10 +3696,12 @@ var Properties = { "azimuth": 1, "backface-visibility": 1, "background": 1, - "background-attachment": 1, + "background-attachment": function(value){ + Validation.oneIdentifier(value, "scroll,fixed,inherit"); + }, "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColor, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, @@ -3626,12 +3717,14 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": 1, - "border-bottom-right-radius": 1, - "border-bottom-style": 1, - "border-bottom-width": 1, - "border-collapse": 1, - "border-color": Validation.oneColor, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": function(value){ + Validation.oneIdentifier(value, "collapse,separate,inherit"); + }, + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -3639,26 +3732,42 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": 1, - "border-left-style": 1, - "border-left-width": 1, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": 1, - "border-right-style": 1, - "border-right-width": 1, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, - "border-style": 1, + "border-style": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderStyle(value.parts[i])){ + throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, "border-top": 1, - "border-top-color": 1, - "border-top-left-radius": 1, - "border-top-right-radius": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "bottom": Validation.measurement, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, + "border-width": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderWidth(value.parts[i])){ + throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": 1, + "box-decoration-break": function(value){ + Validation.oneIdentifier(value, "slice,clone"); + }, "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -3671,17 +3780,14 @@ var Properties = { "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": { - parts: [ - { - types: ["color", "identifier"], - identifier: /^inherit$/i - } - ] + "caption-side": function(value){ + Validation.oneIdentifier(value, "top,bottom,inherit"); }, + "clear": function(value){ + Validation.oneIdentifier(value, "none,right,left,both,inherit"); + }, + "clip": 1, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -3697,11 +3803,15 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": 1, + "cue": function(value){ + Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); + }, "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": 1, + "direction": function(value){ + Validation.oneIdentifier(value, "ltr,rtl,inherit"); + }, "display": 1, "dominant-baseline": 1, "drop-initial-after-adjust": 1, @@ -3711,16 +3821,13 @@ var Properties = { "drop-initial-size": 1, "drop-initial-value": 1, "elevation": 1, - "empty-cells": 1, + "empty-cells": function(value){ + Validation.oneIdentifier(value, "show,hide,inherit"); + }, "fit": 1, "fit-position": 1, - "float": { - parts: [ - { - types: ["identifier"], - identifier: /^(left|right|none|inherit)$/i - } - ] + "float": function(value){ + Validation.oneIdentifier(value, "left,right,none,inherit"); }, "float-offset": 1, @@ -3729,13 +3836,17 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": 1, - "font-variant": 1, + "font-style": function(value){ + Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); + }, + "font-variant": function(value){ + Validation.oneIdentifier(value, "normal,small-caps,inherit"); + }, "font-weight": 1, "grid-columns": 1, "grid-rows": 1, "hanging-punctuation": 1, - "height": Validation.measurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -3747,7 +3858,7 @@ var Properties = { "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.measurement, + "left": Validation.oneMeasurement, "letter-spacing": 1, "line-height": 1, "line-stacking": 1, @@ -3756,8 +3867,12 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, + "list-style-position": function(value){ + Validation.oneIdentifier(value, "inside,outsider,inherit"); + }, + "list-style-type": function(value){ + Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); + }, "margin": 1, "margin-bottom": 1, "margin-left": 1, @@ -3784,11 +3899,15 @@ var Properties = { "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": 1, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": 1, + "overflow": function(value){ + Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); + }, "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, @@ -3798,9 +3917,15 @@ var Properties = { "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, + "page-break-after": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-before": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-inside": function(value){ + Validation.oneIdentifier(value, "auto,avoid,inherit"); + }, "page-policy": 1, "pause": 1, "pause-after": 1, @@ -3811,7 +3936,9 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": 1, + "position": function(value){ + Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); + }, "presentation-level": 1, "punctuation-trim": 1, "quotes": 1, @@ -3821,7 +3948,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.measurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -3829,10 +3956,18 @@ var Properties = { "ruby-position": 1, "ruby-span": 1, "size": 1, - "speak": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, + "speak": function(value){ + Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); + }, + "speak-header": function(value){ + Validation.oneIdentifier(value, "once,always,inherit"); + }, + "speak-numeral": function(value){ + Validation.oneIdentifier(value, "digits,continuous,inherit"); + }, + "speak-punctuation": function(value){ + Validation.oneIdentifier(value, "code,none,inherit"); + }, "speech-rate": 1, "stress": 1, "string-set": 1, @@ -3841,7 +3976,9 @@ var Properties = { "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": 1, + "text-align": function(value){ + Validation.oneIdentifier(value, "left,right,center,justify,inherit"); + }, "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -3850,9 +3987,11 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": 1, + "text-transform": function(value){ + Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); + }, "text-wrap": 1, - "top": Validation.measurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -3861,11 +4000,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": 1, + "unicode-bidi": function(value){ + Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); + }, "user-modify": 1, "user-select": 1, "vertical-align": 1, - "visibility": 1, + "visibility": function(value){ + Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); + }, "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -3875,32 +4018,26 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": 1, + "white-space": function(value){ + Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); + }, "white-space-collapse": 1, "widows": 1, - "width": Validation.measurement, + "width": Validation.oneMeasurement, "word-break": 1, - "word-spacing": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "number", "identifier"], - identifier: /^(normal|inherit)$/, - number: /^0$/ - } - ] - }, + "word-spacing": function(value){ + Validation.oneValue(value); + if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ + throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); + } + }, + "word-wrap": 1, - "z-index": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "identifier"], - identifier: /^(auto|inherit)$/ - } - ] + "z-index": function(value){ + Validation.oneValue(value); + if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ + throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); + } } @@ -5599,6 +5736,7 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); + parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -5618,3 +5756,4 @@ ValidationError :ValidationError }; })(); + diff --git a/src/css/Parser.js b/src/css/Parser.js index 264ecb8c..1c1a5aee 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -1406,7 +1406,7 @@ Parser.prototype = function(){ expr = null, prio = null, error = null, - valid = true; + invalid = null; property = this._property(); if (property !== null){ @@ -1426,8 +1426,7 @@ Parser.prototype = function(){ try { this._validateProperty(property, expr); } catch (ex) { - valid = false; - error = ex; + invalid = ex; } this.fire({ @@ -1437,8 +1436,7 @@ Parser.prototype = function(){ important: prio, line: property.line, col: property.col, - valid: valid, - error: error + invalid: invalid }); return true; @@ -2050,25 +2048,7 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - validation = Properties[name]; - if (typeof validation == "object"){ - for (i=0, len=validation.parts.length; i < len; i++){ - if (!validation.parts[i]){ - throw new ValidationError("Unexpected value. Expected only " + validation.parts.length + " values for property '" + property + "'.", - value.line, value.col); - } else if ((new RegExp("^("+validation.parts[i].types.join("|")+")$")).test(value.parts[i].type)){ - if (validation.parts[i][RegExp.$1]){ - if (!validation.parts[i][RegExp.$1].test(value.parts[i])){ - throw new ValidationError("Unexpected value '" + value.parts[i] + - "'.", value.parts[i].line, value.parts[i].col); - } - } - } else { - throw new ValidationError("Unexpected value type " + value.parts[i].type + - ". Expected " + validation.parts[i].types + ".", value.parts[i].line, value.parts[i].col); - } - } - } + Properties[name](value); //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok diff --git a/src/css/Properties.js b/src/css/Properties.js index f305bcbe..1c559e5e 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -1,22 +1,127 @@ var Validation = { - measurement: { - parts: [ - { - types: ["length", "percentage", "integer", "identifier"], - identifier: /^(auto|inherit)$/i, - integer: /^0$/ - } - ] - }, - oneColor: { - maxParts: 1, - minParts: 1, - parts: [ - { - types: ["color", "identifier"], - identifier: /^(inherit|transparent)$/i - } - ] + + isColor: function(part, other){ + var text = part.text.toString().toLowerCase(), + pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; + + if (part.type != "color"){ + if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ + return false; + } + } + + return true; + }, + + isIdentifier: function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(","), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + isLength: function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + isInteger: function(part){ + return part.type == "integer"; + }, + + isPercentage: function(part){ + return part.type == "percentage" || part == "0"; + }, + + isMeasurement: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + }, + + isBorderWidth: function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + }, + + isBorderStyle: function(part){ + return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + }, + + isBorderSideRadius: function(part){ + return Validation.isLength(part) || Validation.isPercentage(part); + }, + + oneValue: function(value){ + var parts = value.parts; + if (parts.length != 1){ + throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); + } + }, + + maxValues: function(value, max){ + var parts = value.parts; + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); + } + }, + + oneColor: function(value, other){ + var part = value.parts[0], + text = part.text.toString().toLowerCase(); + + Validation.oneValue(value); + + if (!Validation.isColor(part, other)){ + throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); + } + }, + + oneColorOrTransparent: function(value){ + Validation.oneColor(value, "transparent"); + }, + + oneIdentifier: function(value, options){ + + Validation.oneValue(value); + + if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ + throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); + } + }, + + oneMeasurement: function(value){ + Validation.oneValue(value); + if (!Validation.isMeasurement(value.parts[0])){ + throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderWidth: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderWidth(value.parts[0])){ + throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderStyle: function(value){ + Validation.oneValue(value); + if (!Validation.isBorderStyle(value.parts[0])){ + throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); + } + }, + + oneBorderSideRadius: function(value){ + Validation.maxValues(value, 2); + for (var i=0, len= value.parts.length; i < len; i++){ + if (!Validation.isBorderSideRadius(value.parts[i])){ + throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); + } + } } }; @@ -45,10 +150,12 @@ var Properties = { "azimuth": 1, "backface-visibility": 1, "background": 1, - "background-attachment": 1, + "background-attachment": function(value){ + Validation.oneIdentifier(value, "scroll,fixed,inherit"); + }, "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColor, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, @@ -64,12 +171,14 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": 1, - "border-bottom-right-radius": 1, - "border-bottom-style": 1, - "border-bottom-width": 1, - "border-collapse": 1, - "border-color": Validation.oneColor, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": function(value){ + Validation.oneIdentifier(value, "collapse,separate,inherit"); + }, + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -77,26 +186,42 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": 1, - "border-left-style": 1, - "border-left-width": 1, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": 1, - "border-right-style": 1, - "border-right-width": 1, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, - "border-style": 1, + "border-style": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderStyle(value.parts[i])){ + throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, "border-top": 1, - "border-top-color": 1, - "border-top-left-radius": 1, - "border-top-right-radius": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "bottom": Validation.measurement, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, + "border-width": function(value){ + Validation.maxValues(value, 4); + for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ + if (!Validation.isBorderWidth(value.parts[i])){ + throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); + } + } + }, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": 1, + "box-decoration-break": function(value){ + Validation.oneIdentifier(value, "slice,clone"); + }, "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -109,17 +234,14 @@ var Properties = { "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": { - parts: [ - { - types: ["color", "identifier"], - identifier: /^inherit$/i - } - ] + "caption-side": function(value){ + Validation.oneIdentifier(value, "top,bottom,inherit"); + }, + "clear": function(value){ + Validation.oneIdentifier(value, "none,right,left,both,inherit"); }, + "clip": 1, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -135,11 +257,15 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": 1, + "cue": function(value){ + Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); + }, "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": 1, + "direction": function(value){ + Validation.oneIdentifier(value, "ltr,rtl,inherit"); + }, "display": 1, "dominant-baseline": 1, "drop-initial-after-adjust": 1, @@ -149,16 +275,13 @@ var Properties = { "drop-initial-size": 1, "drop-initial-value": 1, "elevation": 1, - "empty-cells": 1, + "empty-cells": function(value){ + Validation.oneIdentifier(value, "show,hide,inherit"); + }, "fit": 1, "fit-position": 1, - "float": { - parts: [ - { - types: ["identifier"], - identifier: /^(left|right|none|inherit)$/i - } - ] + "float": function(value){ + Validation.oneIdentifier(value, "left,right,none,inherit"); }, "float-offset": 1, @@ -167,13 +290,17 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": 1, - "font-variant": 1, + "font-style": function(value){ + Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); + }, + "font-variant": function(value){ + Validation.oneIdentifier(value, "normal,small-caps,inherit"); + }, "font-weight": 1, "grid-columns": 1, "grid-rows": 1, "hanging-punctuation": 1, - "height": Validation.measurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -185,7 +312,7 @@ var Properties = { "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.measurement, + "left": Validation.oneMeasurement, "letter-spacing": 1, "line-height": 1, "line-stacking": 1, @@ -194,8 +321,12 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, + "list-style-position": function(value){ + Validation.oneIdentifier(value, "inside,outsider,inherit"); + }, + "list-style-type": function(value){ + Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); + }, "margin": 1, "margin-bottom": 1, "margin-left": 1, @@ -222,11 +353,15 @@ var Properties = { "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": 1, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": 1, + "overflow": function(value){ + Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); + }, "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, @@ -236,9 +371,15 @@ var Properties = { "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, + "page-break-after": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-before": function(value){ + Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); + }, + "page-break-inside": function(value){ + Validation.oneIdentifier(value, "auto,avoid,inherit"); + }, "page-policy": 1, "pause": 1, "pause-after": 1, @@ -249,7 +390,9 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": 1, + "position": function(value){ + Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); + }, "presentation-level": 1, "punctuation-trim": 1, "quotes": 1, @@ -259,7 +402,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.measurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -267,10 +410,18 @@ var Properties = { "ruby-position": 1, "ruby-span": 1, "size": 1, - "speak": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, + "speak": function(value){ + Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); + }, + "speak-header": function(value){ + Validation.oneIdentifier(value, "once,always,inherit"); + }, + "speak-numeral": function(value){ + Validation.oneIdentifier(value, "digits,continuous,inherit"); + }, + "speak-punctuation": function(value){ + Validation.oneIdentifier(value, "code,none,inherit"); + }, "speech-rate": 1, "stress": 1, "string-set": 1, @@ -279,7 +430,9 @@ var Properties = { "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": 1, + "text-align": function(value){ + Validation.oneIdentifier(value, "left,right,center,justify,inherit"); + }, "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -288,9 +441,11 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": 1, + "text-transform": function(value){ + Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); + }, "text-wrap": 1, - "top": Validation.measurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -299,11 +454,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": 1, + "unicode-bidi": function(value){ + Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); + }, "user-modify": 1, "user-select": 1, "vertical-align": 1, - "visibility": 1, + "visibility": function(value){ + Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); + }, "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -313,32 +472,26 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": 1, + "white-space": function(value){ + Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); + }, "white-space-collapse": 1, "widows": 1, - "width": Validation.measurement, + "width": Validation.oneMeasurement, "word-break": 1, - "word-spacing": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "number", "identifier"], - identifier: /^(normal|inherit)$/, - number: /^0$/ - } - ] - }, + "word-spacing": function(value){ + Validation.oneValue(value); + if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ + throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); + } + }, + "word-wrap": 1, - "z-index": { - minParts: 1, - maxParts: 1, - parts: [ - { - types: ["length", "identifier"], - identifier: /^(auto|inherit)$/ - } - ] + "z-index": function(value){ + Validation.oneValue(value); + if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ + throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); + } } diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index d9a4afb8..a3e73fa2 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1399,6 +1399,213 @@

CSS Parser Tests

assert.areEqual(1, result.parts.length, "Should be one part."); } + })); + + suite.add(new YAHOO.tool.TestCase({ + + name: "Validation Tests", + + testInvalidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected a color but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: foo; }"); + + }, + + testInvalidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected a color but found 'invert'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: invert; }"); + + }, + + testInvalidColor3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected a color but found 'transparent'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: transparent; }"); + + }, + + testValidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: red; }"); + + }, + + testValidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: #ff0000; }"); + + }, + + testValidColor3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: inherit; }"); + + }, + + testValidColor4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-color: transparent; }"); + + }, + + testBackgroundAttachment1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: scroll; }"); + + }, + + testBackgroundAttachment2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: fixed; }"); + + }, + + testBackgroundAttachment3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: inherit; }"); + + }, + + testInvalidBackgroundAttachment: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected one of (scroll,fixed,inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { background-attachment: foo; }"); + }, + + testInvalidZIndex: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected an integer or one of 'auto,inherit' but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { z-index: foo; }"); + }, + + testZIndex1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: 1 }"); + + }, + + testZIndex2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: auto }"); + }, + + testZIndex3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: inherit }"); + + }, + + testBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px }"); + + }, + + testBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px }"); + + }, + + testBorderWidth3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px}"); + + }, + + testBorderWidth4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected a max of 4 property values but found 5.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected a border width but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: foo}"); + + }, + + + + + + + + + })); From bed25554e18e431e3d703a72dae512aae5bd4cad Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 19 Oct 2011 16:54:53 -0700 Subject: [PATCH 008/313] Added src property to validation --- build/node-parserlib.js | 5 +++-- build/parserlib-core.js | 2 +- build/parserlib-css.js | 3 ++- build/parserlib.js | 5 +++-- src/css/Properties.js | 1 + 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index d0a9ecbf..52860157 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3969,6 +3969,7 @@ var Properties = { Validation.oneIdentifier(value, "code,none,inherit"); }, "speech-rate": 1, + "src" : 1, "stress": 1, "string-set": 1, "table-layout": 1, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 4993725d..fb4507d5 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index a2380bb4..c6b8ad32 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3060,6 +3060,7 @@ var Properties = { Validation.oneIdentifier(value, "code,none,inherit"); }, "speech-rate": 1, + "src" : 1, "stress": 1, "string-set": 1, "table-layout": 1, diff --git a/build/parserlib.js b/build/parserlib.js index c4493d42..41051401 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:46:22 */ +/* Build time: 19-October-2011 04:54:46 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3969,6 +3969,7 @@ var Properties = { Validation.oneIdentifier(value, "code,none,inherit"); }, "speech-rate": 1, + "src" : 1, "stress": 1, "string-set": 1, "table-layout": 1, diff --git a/src/css/Properties.js b/src/css/Properties.js index 1c559e5e..6c570670 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -423,6 +423,7 @@ var Properties = { Validation.oneIdentifier(value, "code,none,inherit"); }, "speech-rate": 1, + "src" : 1, "stress": 1, "string-set": 1, "table-layout": 1, From ae59b248f8350ef52a0d868b873d5d060314be83 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 19 Oct 2011 16:58:57 -0700 Subject: [PATCH 009/313] Fixes for validation --- build/node-parserlib.js | 11 +++++++---- build/parserlib-core.js | 2 +- build/parserlib-css.js | 9 ++++++--- build/parserlib.js | 11 +++++++---- src/css/Parser.js | 7 +++++-- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 52860157..bfc15a9f 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3420,11 +3420,14 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - Properties[name](value); + + if (typeof Properties[name] == "function"){ + Properties[name](value); + } //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Property '" + property + "' isn't recognized.", property.line, property.col); + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); } }, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index fb4507d5..02e40b59 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index c6b8ad32..e9a62f06 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2511,11 +2511,14 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - Properties[name](value); + + if (typeof Properties[name] == "function"){ + Properties[name](value); + } //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Property '" + property + "' isn't recognized.", property.line, property.col); + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); } }, diff --git a/build/parserlib.js b/build/parserlib.js index 41051401..f59231a9 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:54:46 */ +/* Build time: 19-October-2011 04:58:41 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3420,11 +3420,14 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - Properties[name](value); + + if (typeof Properties[name] == "function"){ + Properties[name](value); + } //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Property '" + property + "' isn't recognized.", property.line, property.col); + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); } }, diff --git a/src/css/Parser.js b/src/css/Parser.js index 1c1a5aee..d0d47cd3 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -2048,11 +2048,14 @@ Parser.prototype = function(){ i, len; if (Properties[name]){ - Properties[name](value); + + if (typeof Properties[name] == "function"){ + Properties[name](value); + } //otherwise, no validation available yet } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Property '" + property + "' isn't recognized.", property.line, property.col); + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); } }, From bf4f4912fb23c4547cd308f23e7684aa25d364c5 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 19 Oct 2011 17:20:58 -0700 Subject: [PATCH 010/313] A bit more validation --- build/node-parserlib.js | 26 +++++++++++++++++--------- build/parserlib-core.js | 2 +- build/parserlib-css.js | 24 ++++++++++++++++-------- build/parserlib.js | 26 +++++++++++++++++--------- src/css/Properties.js | 22 +++++++++++++++------- 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index bfc15a9f..1d6904de 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3779,7 +3779,9 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": 1, + "box-sizing": function(value){ + Validation.oneIdentifier(value, "content-box,border-box,inherit"); + }, "break-after": 1, "break-before": 1, "break-inside": 1, @@ -3815,7 +3817,9 @@ var Properties = { "direction": function(value){ Validation.oneIdentifier(value, "ltr,rtl,inherit"); }, - "display": 1, + "display": function(value){ + Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); + }, "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3827,6 +3831,7 @@ var Properties = { "empty-cells": function(value){ Validation.oneIdentifier(value, "show,hide,inherit"); }, + "filter": 1, "fit": 1, "fit-position": 1, "float": function(value){ @@ -4007,8 +4012,12 @@ var Properties = { "unicode-bidi": function(value){ Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); }, - "user-modify": 1, - "user-select": 1, + "user-modify": function(value){ + Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); + }, + "user-select": function(value){ + Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); + }, "vertical-align": 1, "visibility": function(value){ Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); @@ -4042,9 +4051,8 @@ var Properties = { if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); } - } - - + }, + "zoom": 1 }; /** * Represents a selector combinator (whitespace, +, >). diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 02e40b59..3bfaf00f 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index e9a62f06..a0540748 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2870,7 +2870,9 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": 1, + "box-sizing": function(value){ + Validation.oneIdentifier(value, "content-box,border-box,inherit"); + }, "break-after": 1, "break-before": 1, "break-inside": 1, @@ -2906,7 +2908,9 @@ var Properties = { "direction": function(value){ Validation.oneIdentifier(value, "ltr,rtl,inherit"); }, - "display": 1, + "display": function(value){ + Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); + }, "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -2918,6 +2922,7 @@ var Properties = { "empty-cells": function(value){ Validation.oneIdentifier(value, "show,hide,inherit"); }, + "filter": 1, "fit": 1, "fit-position": 1, "float": function(value){ @@ -3098,8 +3103,12 @@ var Properties = { "unicode-bidi": function(value){ Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); }, - "user-modify": 1, - "user-select": 1, + "user-modify": function(value){ + Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); + }, + "user-select": function(value){ + Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); + }, "vertical-align": 1, "visibility": function(value){ Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); @@ -3133,9 +3142,8 @@ var Properties = { if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); } - } - - + }, + "zoom": 1 }; /** * Represents a selector combinator (whitespace, +, >). diff --git a/build/parserlib.js b/build/parserlib.js index f59231a9..df26ae84 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 04:58:41 */ +/* Build time: 19-October-2011 05:20:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3779,7 +3779,9 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": 1, + "box-sizing": function(value){ + Validation.oneIdentifier(value, "content-box,border-box,inherit"); + }, "break-after": 1, "break-before": 1, "break-inside": 1, @@ -3815,7 +3817,9 @@ var Properties = { "direction": function(value){ Validation.oneIdentifier(value, "ltr,rtl,inherit"); }, - "display": 1, + "display": function(value){ + Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); + }, "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3827,6 +3831,7 @@ var Properties = { "empty-cells": function(value){ Validation.oneIdentifier(value, "show,hide,inherit"); }, + "filter": 1, "fit": 1, "fit-position": 1, "float": function(value){ @@ -4007,8 +4012,12 @@ var Properties = { "unicode-bidi": function(value){ Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); }, - "user-modify": 1, - "user-select": 1, + "user-modify": function(value){ + Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); + }, + "user-select": function(value){ + Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); + }, "vertical-align": 1, "visibility": function(value){ Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); @@ -4042,9 +4051,8 @@ var Properties = { if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); } - } - - + }, + "zoom": 1 }; /** * Represents a selector combinator (whitespace, +, >). diff --git a/src/css/Properties.js b/src/css/Properties.js index 6c570670..e2b4780d 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -230,7 +230,9 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": 1, + "box-sizing": function(value){ + Validation.oneIdentifier(value, "content-box,border-box,inherit"); + }, "break-after": 1, "break-before": 1, "break-inside": 1, @@ -266,7 +268,9 @@ var Properties = { "direction": function(value){ Validation.oneIdentifier(value, "ltr,rtl,inherit"); }, - "display": 1, + "display": function(value){ + Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); + }, "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -278,6 +282,7 @@ var Properties = { "empty-cells": function(value){ Validation.oneIdentifier(value, "show,hide,inherit"); }, + "filter": 1, "fit": 1, "fit-position": 1, "float": function(value){ @@ -458,8 +463,12 @@ var Properties = { "unicode-bidi": function(value){ Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); }, - "user-modify": 1, - "user-select": 1, + "user-modify": function(value){ + Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); + }, + "user-select": function(value){ + Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); + }, "vertical-align": 1, "visibility": function(value){ Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); @@ -493,7 +502,6 @@ var Properties = { if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); } - } - - + }, + "zoom": 1 }; \ No newline at end of file From c3cecae487743c0facc6600662f7bb1dbfa4b6ef Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 20 Oct 2011 11:56:47 -0700 Subject: [PATCH 011/313] Changes for compatibility with WSH --- build/node-parserlib.js | 8 ++++---- build/parserlib-core.js | 6 +++--- build/parserlib-css.js | 2 +- build/parserlib.js | 8 ++++---- src/util/EventTarget.js | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 1d6904de..24996345 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ var parserlib = {}; (function(){ @@ -74,11 +74,11 @@ EventTarget.prototype = { if (typeof event == "string"){ event = { type: event }; } - if (!event.target){ + if (typeof event.target != "undefined"){ event.target = this; } - if (!event.type){ + if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 3bfaf00f..ecfbc8c6 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ var parserlib = {}; (function(){ @@ -74,11 +74,11 @@ EventTarget.prototype = { if (typeof event == "string"){ event = { type: event }; } - if (!event.target){ + if (typeof event.target != "undefined"){ event.target = this; } - if (!event.type){ + if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } diff --git a/build/parserlib-css.js b/build/parserlib-css.js index a0540748..3e2131fa 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib.js b/build/parserlib.js index df26ae84..3c25b76a 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ var parserlib = {}; (function(){ @@ -74,11 +74,11 @@ EventTarget.prototype = { if (typeof event == "string"){ event = { type: event }; } - if (!event.target){ + if (typeof event.target != "undefined"){ event.target = this; } - if (!event.type){ + if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 19-October-2011 05:20:53 */ +/* Build time: 20-October-2011 11:56:31 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/src/util/EventTarget.js b/src/util/EventTarget.js index 215abe74..a3ea22d6 100644 --- a/src/util/EventTarget.js +++ b/src/util/EventTarget.js @@ -47,11 +47,11 @@ EventTarget.prototype = { if (typeof event == "string"){ event = { type: event }; } - if (!event.target){ + if (typeof event.target != "undefined"){ event.target = this; } - if (!event.type){ + if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } From 71189d99b0ce93c6b4927572242041b0eecca90b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 20 Oct 2011 13:03:47 -0700 Subject: [PATCH 012/313] Added a bunch more validation --- build/node-parserlib.js | 496 ++++++++++++----------------------- build/parserlib-core.js | 2 +- build/parserlib-css.js | 494 ++++++++++++---------------------- build/parserlib.js | 496 ++++++++++++----------------------- src/css/Level1Properties.js | 67 ----- src/css/Level2Properties.js | 109 -------- src/css/Properties.js | 332 ++++++++++++----------- tests/css/CSSParserTests.htm | 39 ++- 8 files changed, 709 insertions(+), 1326 deletions(-) delete mode 100644 src/css/Level1Properties.js delete mode 100644 src/css/Level2Properties.js diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 24996345..6c5bcc97 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1119,182 +1119,6 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - -var Level1Properties = { - - "background": 1, - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - - "border": 1, - "border-bottom": 1, - "border-bottom-width": 1, - "border-color": 1, - "border-left": 1, - "border-left-width": 1, - "border-right": 1, - "border-right-width": 1, - "border-style": 1, - "border-top": 1, - "border-top-width": 1, - "border-width": 1, - - "clear": 1, - "color": 1, - "display": 1, - "float": 1, - - "font": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - - "height": 1, - "letter-spacing": 1, - "line-height": 1, - - "list-style": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - - "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, - - "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, - - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - - "vertical-align": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1 - -}; - -var Level2Properties = { - - //Aural - "azimuth": 1, - "cue-after": 1, - "cue-before": 1, - "cue": 1, - "elevation": 1, - "pause-after": 1, - "pause-before": 1, - "pause": 1, - "pitch-range": 1, - "pitch": 1, - "play-during": 1, - "richness": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, - "speak": 1, - "speech-rate": 1, - "stress": 1, - "voice-family": 1, - "volume": 1, - - //Paged - "orphans": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, - "widows": 1, - - //Interactive - "cursor": 1, - "outline-color": 1, - "outline-style": 1, - "outline-width": 1, - "outline": 1, - - //Visual - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - "background": 1, - "border-collapse": 1, - "border-color": 1, - "border-spacing": 1, - "border-style": 1, - "border-top": 1, - "border-top-color": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "border": 1, - "bottom": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": 1, - "content": 1, - "counter-increment": 1, - "counter-reset": 1, - "direction": 1, - "display": 1, - "empty-cells": 1, - "float": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - "font": 1, - "height": 1, - "left": 1, - "letter-spacing": 1, - "line-height": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - "list-style": 1, - "margin-right": 1, - "margin-top": 1, - "margin": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, - "min-width": 1, - "overflow": 1, - "padding-top": 1, - "padding": 1, - "position": 1, - "quotes": 1, - "right": 1, - "table-layout": 1, - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - "top": 1, - "unicode-bidi": 1, - "vertical-align": 1, - "visibility": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1, - "z-index": 1 -}; /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -3564,7 +3388,7 @@ var Validation = { isIdentifier: function(part, options){ var text = part.text.toString().toLowerCase(), - args = options.split(","), + args = options.split(" | "), i, len, found = false; @@ -3585,20 +3409,24 @@ var Validation = { return part.type == "integer"; }, + isURI: function(part){ + return part.type == "uri"; + }, + isPercentage: function(part){ return part.type == "percentage" || part == "0"; }, isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); }, isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); }, isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, isBorderSideRadius: function(part){ @@ -3674,7 +3502,14 @@ var Validation = { } }; - +var ValidationType = { + "integer": Validation.isInteger, + "uri": Validation.isURI, + "color": Validation.isColor, + "length": Validation.isLength, + "percentage": Validation.isPercentage, + "measurement": Validation.isMeasurement +}; @@ -3684,6 +3519,7 @@ var Validation = { var Properties = { + //A "alignment-adjust": 1, "alignment-baseline": 1, "animation": 1, @@ -3697,18 +3533,18 @@ var Properties = { "animation-timing-function": 1, "appearance": 1, "azimuth": 1, + + //B "backface-visibility": 1, "background": 1, - "background-attachment": function(value){ - Validation.oneIdentifier(value, "scroll,fixed,inherit"); - }, + "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, - "background-repeat": 1, + "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, "baseline-shift": 1, "binding": 1, @@ -3720,14 +3556,12 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, - "border-collapse": function(value){ - Validation.oneIdentifier(value, "collapse,separate,inherit"); - }, - "border-color": Validation.oneColorOrTransparent, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": [ "collapse | separate | inherit" ], + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -3735,14 +3569,14 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -3753,11 +3587,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -3766,11 +3600,9 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": function(value){ - Validation.oneIdentifier(value, "slice,clone"); - }, + "box-decoration-break": [ "slice |clone" ], "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -3779,20 +3611,16 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": function(value){ - Validation.oneIdentifier(value, "content-box,border-box,inherit"); - }, + "box-sizing": [ "content-box | border-box | inherit" ], "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": function(value){ - Validation.oneIdentifier(value, "top,bottom,inherit"); - }, - "clear": function(value){ - Validation.oneIdentifier(value, "none,right,left,both,inherit"); - }, + + //C + "caption-side": [ "top | bottom | inherit" ], + "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -3808,18 +3636,14 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": function(value){ - Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); - }, + "cue": [ "cue-after | cue-before | inherit" ], "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": function(value){ - Validation.oneIdentifier(value, "ltr,rtl,inherit"); - }, - "display": function(value){ - Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); - }, + + //D + "direction": [ "ltr | rtl | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3827,16 +3651,16 @@ var Properties = { "drop-initial-before-align": 1, "drop-initial-size": 1, "drop-initial-value": 1, + + //E "elevation": 1, - "empty-cells": function(value){ - Validation.oneIdentifier(value, "show,hide,inherit"); - }, + "empty-cells": [ "show | hide | inherit" ], + + //F "filter": 1, "fit": 1, "fit-position": 1, - "float": function(value){ - Validation.oneIdentifier(value, "left,right,none,inherit"); - }, + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, @@ -3844,48 +3668,50 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": function(value){ - Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); - }, - "font-variant": function(value){ - Validation.oneIdentifier(value, "normal,small-caps,inherit"); - }, - "font-weight": 1, + "font-style": [ "normal | italic | oblique | inherit" ], + "font-variant": [ "normal | small-caps | inherit" ], + "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], + + //G "grid-columns": 1, "grid-rows": 1, + + //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, "hyphenate-lines": 1, "hyphenate-resource": 1, "hyphens": 1, + + //I "icon": 1, "image-orientation": 1, "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.oneMeasurement, - "letter-spacing": 1, - "line-height": 1, + + //L + "left": Validation.oneMeasurement, + "letter-spacing": [ "length", "normal | inherit" ], + "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, "line-stacking-strategy": 1, "list-style": 1, - "list-style-image": 1, - "list-style-position": function(value){ - Validation.oneIdentifier(value, "inside,outsider,inherit"); - }, - "list-style-type": function(value){ - Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); - }, + "list-style-image": [ "uri", "none | inherit" ], + "list-style-position": [ "inside | outsider | inherit" ], + "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], + + //M "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, + "margin-bottom": [ "length", "percentage", "auto | inherit" ], + "margin-left": [ "length", "percentage", "auto | inherit" ], + "margin-right": [ "length", "percentage", "auto | inherit" ], + "margin-top": [ "length", "percentage", "auto | inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -3894,46 +3720,44 @@ var Properties = { "marquee-play-count": 1, "marquee-speed": 1, "marquee-style": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, + "max-height": [ "length", "percentage", "none | inherit" ], + "max-width": [ "length", "percentage", "none | inherit" ], + "min-height": [ "length", "percentage", "inherit" ], "min-width": 1, "move-to": 1, + + //N "nav-down": 1, "nav-index": 1, "nav-left": 1, "nav-right": 1, "nav-up": 1, + + //O "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": function(value){ - Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); - }, + "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, + + //P "padding": 1, "padding-bottom": 1, "padding-left": 1, "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-before": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-inside": function(value){ - Validation.oneIdentifier(value, "auto,avoid,inherit"); - }, + "page-break-after": [ "auto | always | avoid | left | right | inherit" ], + "page-break-before": [ "auto | always | avoid | left | right | inherit" ], + "page-break-inside": [ "auto | avoid | inherit" ], "page-policy": 1, "pause": 1, "pause-after": 1, @@ -3944,50 +3768,45 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": function(value){ - Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); - }, + "position": [ "static | relative | absolute | fixed | inherit" ], "presentation-level": 1, "punctuation-trim": 1, + + //Q "quotes": 1, + + //R "rendering-intent": 1, "resize": 1, "rest": 1, "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, "ruby-overhang": 1, "ruby-position": 1, "ruby-span": 1, + + //S "size": 1, - "speak": function(value){ - Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); - }, - "speak-header": function(value){ - Validation.oneIdentifier(value, "once,always,inherit"); - }, - "speak-numeral": function(value){ - Validation.oneIdentifier(value, "digits,continuous,inherit"); - }, - "speak-punctuation": function(value){ - Validation.oneIdentifier(value, "code,none,inherit"); - }, + "speak": [ "normal | none | spell-out | inherit" ], + "speak-header": [ "once | always | inherit" ], + "speak-numeral": [ "digits | continuous | inherit" ], + "speak-punctuation": [ "code | none | inherit" ], "speech-rate": 1, "src" : 1, "stress": 1, "string-set": 1, - "table-layout": 1, + + "table-layout": [ "auto | fixed | inherit" ], "target": 1, "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": function(value){ - Validation.oneIdentifier(value, "left,right,center,justify,inherit"); - }, + "text-align": [ "left | right | center | justify | inherit" ], "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -3996,11 +3815,9 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": function(value){ - Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); - }, + "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -4009,19 +3826,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": function(value){ - Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); - }, - "user-modify": function(value){ - Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); - }, - "user-select": function(value){ - Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); - }, + + //U + "unicode-bidi": [ "normal | embed | bidi-override | inherit" ], + "user-modify": [ "read-only | read-write | write-only | inherit" ], + "user-select": [ "none | text | toggle | element | elements | all | inherit" ], + + //V "vertical-align": 1, - "visibility": function(value){ - Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); - }, + "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -4031,29 +3844,54 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": function(value){ - Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); - }, + + //W + "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, "widows": 1, - "width": Validation.oneMeasurement, + "width": [ "measurement" ], "word-break": 1, - "word-spacing": function(value){ - Validation.oneValue(value); - if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ - throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); - } - }, - + "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, - "z-index": function(value){ - Validation.oneValue(value); - if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ - throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); - } - }, + + //Z + "z-index": [ "integer", "auto | inherit" ], "zoom": 1 }; + +//Create validation functions for strings +(function(){ + var prop; + for (prop in Properties){ + if (Properties.hasOwnProperty(prop)){ + if (Properties[prop] instanceof Array){ + Properties[prop] = (function(values){ + return function(value){ + var valid = false, + msg = [], + part = value.parts[0]; + + Validation.oneValue(value); + + for (var i=0, len=values.length; i < len && !valid; i++){ + if (typeof ValidationType[values[i]] == "undefined"){ + valid = valid || Validation.isIdentifier(part, values[i]); + msg.push("one of (" + values[i] + ")"); + } else { + valid = valid || ValidationType[values[i]](part); + msg.push(values[i]); + } + } + + if (!valid){ + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); + } + }; + })(Properties[prop]); + } + } + } +})(); /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css diff --git a/build/parserlib-core.js b/build/parserlib-core.js index ecfbc8c6..8c82e116 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 3e2131fa..d6f944e5 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -210,182 +210,6 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - -var Level1Properties = { - - "background": 1, - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - - "border": 1, - "border-bottom": 1, - "border-bottom-width": 1, - "border-color": 1, - "border-left": 1, - "border-left-width": 1, - "border-right": 1, - "border-right-width": 1, - "border-style": 1, - "border-top": 1, - "border-top-width": 1, - "border-width": 1, - - "clear": 1, - "color": 1, - "display": 1, - "float": 1, - - "font": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - - "height": 1, - "letter-spacing": 1, - "line-height": 1, - - "list-style": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - - "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, - - "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, - - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - - "vertical-align": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1 - -}; - -var Level2Properties = { - - //Aural - "azimuth": 1, - "cue-after": 1, - "cue-before": 1, - "cue": 1, - "elevation": 1, - "pause-after": 1, - "pause-before": 1, - "pause": 1, - "pitch-range": 1, - "pitch": 1, - "play-during": 1, - "richness": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, - "speak": 1, - "speech-rate": 1, - "stress": 1, - "voice-family": 1, - "volume": 1, - - //Paged - "orphans": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, - "widows": 1, - - //Interactive - "cursor": 1, - "outline-color": 1, - "outline-style": 1, - "outline-width": 1, - "outline": 1, - - //Visual - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - "background": 1, - "border-collapse": 1, - "border-color": 1, - "border-spacing": 1, - "border-style": 1, - "border-top": 1, - "border-top-color": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "border": 1, - "bottom": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": 1, - "content": 1, - "counter-increment": 1, - "counter-reset": 1, - "direction": 1, - "display": 1, - "empty-cells": 1, - "float": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - "font": 1, - "height": 1, - "left": 1, - "letter-spacing": 1, - "line-height": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - "list-style": 1, - "margin-right": 1, - "margin-top": 1, - "margin": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, - "min-width": 1, - "overflow": 1, - "padding-top": 1, - "padding": 1, - "position": 1, - "quotes": 1, - "right": 1, - "table-layout": 1, - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - "top": 1, - "unicode-bidi": 1, - "vertical-align": 1, - "visibility": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1, - "z-index": 1 -}; /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -2655,7 +2479,7 @@ var Validation = { isIdentifier: function(part, options){ var text = part.text.toString().toLowerCase(), - args = options.split(","), + args = options.split(" | "), i, len, found = false; @@ -2676,20 +2500,24 @@ var Validation = { return part.type == "integer"; }, + isURI: function(part){ + return part.type == "uri"; + }, + isPercentage: function(part){ return part.type == "percentage" || part == "0"; }, isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); }, isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); }, isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, isBorderSideRadius: function(part){ @@ -2765,7 +2593,14 @@ var Validation = { } }; - +var ValidationType = { + "integer": Validation.isInteger, + "uri": Validation.isURI, + "color": Validation.isColor, + "length": Validation.isLength, + "percentage": Validation.isPercentage, + "measurement": Validation.isMeasurement +}; @@ -2775,6 +2610,7 @@ var Validation = { var Properties = { + //A "alignment-adjust": 1, "alignment-baseline": 1, "animation": 1, @@ -2788,18 +2624,18 @@ var Properties = { "animation-timing-function": 1, "appearance": 1, "azimuth": 1, + + //B "backface-visibility": 1, "background": 1, - "background-attachment": function(value){ - Validation.oneIdentifier(value, "scroll,fixed,inherit"); - }, + "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, - "background-repeat": 1, + "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, "baseline-shift": 1, "binding": 1, @@ -2811,14 +2647,12 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, - "border-collapse": function(value){ - Validation.oneIdentifier(value, "collapse,separate,inherit"); - }, - "border-color": Validation.oneColorOrTransparent, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": [ "collapse | separate | inherit" ], + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -2826,14 +2660,14 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -2844,11 +2678,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -2857,11 +2691,9 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": function(value){ - Validation.oneIdentifier(value, "slice,clone"); - }, + "box-decoration-break": [ "slice |clone" ], "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -2870,20 +2702,16 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": function(value){ - Validation.oneIdentifier(value, "content-box,border-box,inherit"); - }, + "box-sizing": [ "content-box | border-box | inherit" ], "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": function(value){ - Validation.oneIdentifier(value, "top,bottom,inherit"); - }, - "clear": function(value){ - Validation.oneIdentifier(value, "none,right,left,both,inherit"); - }, + + //C + "caption-side": [ "top | bottom | inherit" ], + "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -2899,18 +2727,14 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": function(value){ - Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); - }, + "cue": [ "cue-after | cue-before | inherit" ], "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": function(value){ - Validation.oneIdentifier(value, "ltr,rtl,inherit"); - }, - "display": function(value){ - Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); - }, + + //D + "direction": [ "ltr | rtl | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -2918,16 +2742,16 @@ var Properties = { "drop-initial-before-align": 1, "drop-initial-size": 1, "drop-initial-value": 1, + + //E "elevation": 1, - "empty-cells": function(value){ - Validation.oneIdentifier(value, "show,hide,inherit"); - }, + "empty-cells": [ "show | hide | inherit" ], + + //F "filter": 1, "fit": 1, "fit-position": 1, - "float": function(value){ - Validation.oneIdentifier(value, "left,right,none,inherit"); - }, + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, @@ -2935,48 +2759,50 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": function(value){ - Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); - }, - "font-variant": function(value){ - Validation.oneIdentifier(value, "normal,small-caps,inherit"); - }, - "font-weight": 1, + "font-style": [ "normal | italic | oblique | inherit" ], + "font-variant": [ "normal | small-caps | inherit" ], + "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], + + //G "grid-columns": 1, "grid-rows": 1, + + //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, "hyphenate-lines": 1, "hyphenate-resource": 1, "hyphens": 1, + + //I "icon": 1, "image-orientation": 1, "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.oneMeasurement, - "letter-spacing": 1, - "line-height": 1, + + //L + "left": Validation.oneMeasurement, + "letter-spacing": [ "length", "normal | inherit" ], + "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, "line-stacking-strategy": 1, "list-style": 1, - "list-style-image": 1, - "list-style-position": function(value){ - Validation.oneIdentifier(value, "inside,outsider,inherit"); - }, - "list-style-type": function(value){ - Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); - }, + "list-style-image": [ "uri", "none | inherit" ], + "list-style-position": [ "inside | outsider | inherit" ], + "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], + + //M "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, + "margin-bottom": [ "length", "percentage", "auto | inherit" ], + "margin-left": [ "length", "percentage", "auto | inherit" ], + "margin-right": [ "length", "percentage", "auto | inherit" ], + "margin-top": [ "length", "percentage", "auto | inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -2985,46 +2811,44 @@ var Properties = { "marquee-play-count": 1, "marquee-speed": 1, "marquee-style": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, + "max-height": [ "length", "percentage", "none | inherit" ], + "max-width": [ "length", "percentage", "none | inherit" ], + "min-height": [ "length", "percentage", "inherit" ], "min-width": 1, "move-to": 1, + + //N "nav-down": 1, "nav-index": 1, "nav-left": 1, "nav-right": 1, "nav-up": 1, + + //O "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": function(value){ - Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); - }, + "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, + + //P "padding": 1, "padding-bottom": 1, "padding-left": 1, "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-before": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-inside": function(value){ - Validation.oneIdentifier(value, "auto,avoid,inherit"); - }, + "page-break-after": [ "auto | always | avoid | left | right | inherit" ], + "page-break-before": [ "auto | always | avoid | left | right | inherit" ], + "page-break-inside": [ "auto | avoid | inherit" ], "page-policy": 1, "pause": 1, "pause-after": 1, @@ -3035,50 +2859,45 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": function(value){ - Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); - }, + "position": [ "static | relative | absolute | fixed | inherit" ], "presentation-level": 1, "punctuation-trim": 1, + + //Q "quotes": 1, + + //R "rendering-intent": 1, "resize": 1, "rest": 1, "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, "ruby-overhang": 1, "ruby-position": 1, "ruby-span": 1, + + //S "size": 1, - "speak": function(value){ - Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); - }, - "speak-header": function(value){ - Validation.oneIdentifier(value, "once,always,inherit"); - }, - "speak-numeral": function(value){ - Validation.oneIdentifier(value, "digits,continuous,inherit"); - }, - "speak-punctuation": function(value){ - Validation.oneIdentifier(value, "code,none,inherit"); - }, + "speak": [ "normal | none | spell-out | inherit" ], + "speak-header": [ "once | always | inherit" ], + "speak-numeral": [ "digits | continuous | inherit" ], + "speak-punctuation": [ "code | none | inherit" ], "speech-rate": 1, "src" : 1, "stress": 1, "string-set": 1, - "table-layout": 1, + + "table-layout": [ "auto | fixed | inherit" ], "target": 1, "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": function(value){ - Validation.oneIdentifier(value, "left,right,center,justify,inherit"); - }, + "text-align": [ "left | right | center | justify | inherit" ], "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -3087,11 +2906,9 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": function(value){ - Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); - }, + "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -3100,19 +2917,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": function(value){ - Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); - }, - "user-modify": function(value){ - Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); - }, - "user-select": function(value){ - Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); - }, + + //U + "unicode-bidi": [ "normal | embed | bidi-override | inherit" ], + "user-modify": [ "read-only | read-write | write-only | inherit" ], + "user-select": [ "none | text | toggle | element | elements | all | inherit" ], + + //V "vertical-align": 1, - "visibility": function(value){ - Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); - }, + "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -3122,29 +2935,54 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": function(value){ - Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); - }, + + //W + "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, "widows": 1, - "width": Validation.oneMeasurement, + "width": [ "measurement" ], "word-break": 1, - "word-spacing": function(value){ - Validation.oneValue(value); - if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ - throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); - } - }, - + "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, - "z-index": function(value){ - Validation.oneValue(value); - if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ - throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); - } - }, + + //Z + "z-index": [ "integer", "auto | inherit" ], "zoom": 1 }; + +//Create validation functions for strings +(function(){ + var prop; + for (prop in Properties){ + if (Properties.hasOwnProperty(prop)){ + if (Properties[prop] instanceof Array){ + Properties[prop] = (function(values){ + return function(value){ + var valid = false, + msg = [], + part = value.parts[0]; + + Validation.oneValue(value); + + for (var i=0, len=values.length; i < len && !valid; i++){ + if (typeof ValidationType[values[i]] == "undefined"){ + valid = valid || Validation.isIdentifier(part, values[i]); + msg.push("one of (" + values[i] + ")"); + } else { + valid = valid || ValidationType[values[i]](part); + msg.push(values[i]); + } + } + + if (!valid){ + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); + } + }; + })(Properties[prop]); + } + } + } +})(); /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css diff --git a/build/parserlib.js b/build/parserlib.js index 3c25b76a..d53ee617 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 11:56:31 */ +/* Build time: 20-October-2011 12:57:45 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1119,182 +1119,6 @@ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - -var Level1Properties = { - - "background": 1, - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - - "border": 1, - "border-bottom": 1, - "border-bottom-width": 1, - "border-color": 1, - "border-left": 1, - "border-left-width": 1, - "border-right": 1, - "border-right-width": 1, - "border-style": 1, - "border-top": 1, - "border-top-width": 1, - "border-width": 1, - - "clear": 1, - "color": 1, - "display": 1, - "float": 1, - - "font": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - - "height": 1, - "letter-spacing": 1, - "line-height": 1, - - "list-style": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - - "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, - - "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, - - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - - "vertical-align": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1 - -}; - -var Level2Properties = { - - //Aural - "azimuth": 1, - "cue-after": 1, - "cue-before": 1, - "cue": 1, - "elevation": 1, - "pause-after": 1, - "pause-before": 1, - "pause": 1, - "pitch-range": 1, - "pitch": 1, - "play-during": 1, - "richness": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, - "speak": 1, - "speech-rate": 1, - "stress": 1, - "voice-family": 1, - "volume": 1, - - //Paged - "orphans": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, - "widows": 1, - - //Interactive - "cursor": 1, - "outline-color": 1, - "outline-style": 1, - "outline-width": 1, - "outline": 1, - - //Visual - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - "background": 1, - "border-collapse": 1, - "border-color": 1, - "border-spacing": 1, - "border-style": 1, - "border-top": 1, - "border-top-color": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "border": 1, - "bottom": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": 1, - "content": 1, - "counter-increment": 1, - "counter-reset": 1, - "direction": 1, - "display": 1, - "empty-cells": 1, - "float": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - "font": 1, - "height": 1, - "left": 1, - "letter-spacing": 1, - "line-height": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - "list-style": 1, - "margin-right": 1, - "margin-top": 1, - "margin": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, - "min-width": 1, - "overflow": 1, - "padding-top": 1, - "padding": 1, - "position": 1, - "quotes": 1, - "right": 1, - "table-layout": 1, - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - "top": 1, - "unicode-bidi": 1, - "vertical-align": 1, - "visibility": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1, - "z-index": 1 -}; /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -3564,7 +3388,7 @@ var Validation = { isIdentifier: function(part, options){ var text = part.text.toString().toLowerCase(), - args = options.split(","), + args = options.split(" | "), i, len, found = false; @@ -3585,20 +3409,24 @@ var Validation = { return part.type == "integer"; }, + isURI: function(part){ + return part.type == "uri"; + }, + isPercentage: function(part){ return part.type == "percentage" || part == "0"; }, isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); }, isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); }, isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, isBorderSideRadius: function(part){ @@ -3674,7 +3502,14 @@ var Validation = { } }; - +var ValidationType = { + "integer": Validation.isInteger, + "uri": Validation.isURI, + "color": Validation.isColor, + "length": Validation.isLength, + "percentage": Validation.isPercentage, + "measurement": Validation.isMeasurement +}; @@ -3684,6 +3519,7 @@ var Validation = { var Properties = { + //A "alignment-adjust": 1, "alignment-baseline": 1, "animation": 1, @@ -3697,18 +3533,18 @@ var Properties = { "animation-timing-function": 1, "appearance": 1, "azimuth": 1, + + //B "backface-visibility": 1, "background": 1, - "background-attachment": function(value){ - Validation.oneIdentifier(value, "scroll,fixed,inherit"); - }, + "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, - "background-repeat": 1, + "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, "baseline-shift": 1, "binding": 1, @@ -3720,14 +3556,12 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, - "border-collapse": function(value){ - Validation.oneIdentifier(value, "collapse,separate,inherit"); - }, - "border-color": Validation.oneColorOrTransparent, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": [ "collapse | separate | inherit" ], + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -3735,14 +3569,14 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -3753,11 +3587,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -3766,11 +3600,9 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": function(value){ - Validation.oneIdentifier(value, "slice,clone"); - }, + "box-decoration-break": [ "slice |clone" ], "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -3779,20 +3611,16 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": function(value){ - Validation.oneIdentifier(value, "content-box,border-box,inherit"); - }, + "box-sizing": [ "content-box | border-box | inherit" ], "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": function(value){ - Validation.oneIdentifier(value, "top,bottom,inherit"); - }, - "clear": function(value){ - Validation.oneIdentifier(value, "none,right,left,both,inherit"); - }, + + //C + "caption-side": [ "top | bottom | inherit" ], + "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -3808,18 +3636,14 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": function(value){ - Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); - }, + "cue": [ "cue-after | cue-before | inherit" ], "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": function(value){ - Validation.oneIdentifier(value, "ltr,rtl,inherit"); - }, - "display": function(value){ - Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); - }, + + //D + "direction": [ "ltr | rtl | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3827,16 +3651,16 @@ var Properties = { "drop-initial-before-align": 1, "drop-initial-size": 1, "drop-initial-value": 1, + + //E "elevation": 1, - "empty-cells": function(value){ - Validation.oneIdentifier(value, "show,hide,inherit"); - }, + "empty-cells": [ "show | hide | inherit" ], + + //F "filter": 1, "fit": 1, "fit-position": 1, - "float": function(value){ - Validation.oneIdentifier(value, "left,right,none,inherit"); - }, + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, @@ -3844,48 +3668,50 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": function(value){ - Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); - }, - "font-variant": function(value){ - Validation.oneIdentifier(value, "normal,small-caps,inherit"); - }, - "font-weight": 1, + "font-style": [ "normal | italic | oblique | inherit" ], + "font-variant": [ "normal | small-caps | inherit" ], + "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], + + //G "grid-columns": 1, "grid-rows": 1, + + //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, "hyphenate-lines": 1, "hyphenate-resource": 1, "hyphens": 1, + + //I "icon": 1, "image-orientation": 1, "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.oneMeasurement, - "letter-spacing": 1, - "line-height": 1, + + //L + "left": Validation.oneMeasurement, + "letter-spacing": [ "length", "normal | inherit" ], + "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, "line-stacking-strategy": 1, "list-style": 1, - "list-style-image": 1, - "list-style-position": function(value){ - Validation.oneIdentifier(value, "inside,outsider,inherit"); - }, - "list-style-type": function(value){ - Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); - }, + "list-style-image": [ "uri", "none | inherit" ], + "list-style-position": [ "inside | outsider | inherit" ], + "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], + + //M "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, + "margin-bottom": [ "length", "percentage", "auto | inherit" ], + "margin-left": [ "length", "percentage", "auto | inherit" ], + "margin-right": [ "length", "percentage", "auto | inherit" ], + "margin-top": [ "length", "percentage", "auto | inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -3894,46 +3720,44 @@ var Properties = { "marquee-play-count": 1, "marquee-speed": 1, "marquee-style": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, + "max-height": [ "length", "percentage", "none | inherit" ], + "max-width": [ "length", "percentage", "none | inherit" ], + "min-height": [ "length", "percentage", "inherit" ], "min-width": 1, "move-to": 1, + + //N "nav-down": 1, "nav-index": 1, "nav-left": 1, "nav-right": 1, "nav-up": 1, + + //O "opacity": 1, "orphans": 1, "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": function(value){ + Validation.oneColor(value, "invert"); + }, "outline-offset": 1, "outline-style": 1, "outline-width": 1, - "overflow": function(value){ - Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); - }, + "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, + + //P "padding": 1, "padding-bottom": 1, "padding-left": 1, "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-before": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-inside": function(value){ - Validation.oneIdentifier(value, "auto,avoid,inherit"); - }, + "page-break-after": [ "auto | always | avoid | left | right | inherit" ], + "page-break-before": [ "auto | always | avoid | left | right | inherit" ], + "page-break-inside": [ "auto | avoid | inherit" ], "page-policy": 1, "pause": 1, "pause-after": 1, @@ -3944,50 +3768,45 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": function(value){ - Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); - }, + "position": [ "static | relative | absolute | fixed | inherit" ], "presentation-level": 1, "punctuation-trim": 1, + + //Q "quotes": 1, + + //R "rendering-intent": 1, "resize": 1, "rest": 1, "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, "ruby-overhang": 1, "ruby-position": 1, "ruby-span": 1, + + //S "size": 1, - "speak": function(value){ - Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); - }, - "speak-header": function(value){ - Validation.oneIdentifier(value, "once,always,inherit"); - }, - "speak-numeral": function(value){ - Validation.oneIdentifier(value, "digits,continuous,inherit"); - }, - "speak-punctuation": function(value){ - Validation.oneIdentifier(value, "code,none,inherit"); - }, + "speak": [ "normal | none | spell-out | inherit" ], + "speak-header": [ "once | always | inherit" ], + "speak-numeral": [ "digits | continuous | inherit" ], + "speak-punctuation": [ "code | none | inherit" ], "speech-rate": 1, "src" : 1, "stress": 1, "string-set": 1, - "table-layout": 1, + + "table-layout": [ "auto | fixed | inherit" ], "target": 1, "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": function(value){ - Validation.oneIdentifier(value, "left,right,center,justify,inherit"); - }, + "text-align": [ "left | right | center | justify | inherit" ], "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, @@ -3996,11 +3815,9 @@ var Properties = { "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": function(value){ - Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); - }, + "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -4009,19 +3826,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": function(value){ - Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); - }, - "user-modify": function(value){ - Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); - }, - "user-select": function(value){ - Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); - }, + + //U + "unicode-bidi": [ "normal | embed | bidi-override | inherit" ], + "user-modify": [ "read-only | read-write | write-only | inherit" ], + "user-select": [ "none | text | toggle | element | elements | all | inherit" ], + + //V "vertical-align": 1, - "visibility": function(value){ - Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); - }, + "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -4031,29 +3844,54 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": function(value){ - Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); - }, + + //W + "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, "widows": 1, - "width": Validation.oneMeasurement, + "width": [ "measurement" ], "word-break": 1, - "word-spacing": function(value){ - Validation.oneValue(value); - if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ - throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); - } - }, - + "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, - "z-index": function(value){ - Validation.oneValue(value); - if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ - throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); - } - }, + + //Z + "z-index": [ "integer", "auto | inherit" ], "zoom": 1 }; + +//Create validation functions for strings +(function(){ + var prop; + for (prop in Properties){ + if (Properties.hasOwnProperty(prop)){ + if (Properties[prop] instanceof Array){ + Properties[prop] = (function(values){ + return function(value){ + var valid = false, + msg = [], + part = value.parts[0]; + + Validation.oneValue(value); + + for (var i=0, len=values.length; i < len && !valid; i++){ + if (typeof ValidationType[values[i]] == "undefined"){ + valid = valid || Validation.isIdentifier(part, values[i]); + msg.push("one of (" + values[i] + ")"); + } else { + valid = valid || ValidationType[values[i]](part); + msg.push(values[i]); + } + } + + if (!valid){ + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); + } + }; + })(Properties[prop]); + } + } + } +})(); /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css diff --git a/src/css/Level1Properties.js b/src/css/Level1Properties.js deleted file mode 100644 index c7eaef1e..00000000 --- a/src/css/Level1Properties.js +++ /dev/null @@ -1,67 +0,0 @@ - -var Level1Properties = { - - "background": 1, - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - - "border": 1, - "border-bottom": 1, - "border-bottom-width": 1, - "border-color": 1, - "border-left": 1, - "border-left-width": 1, - "border-right": 1, - "border-right-width": 1, - "border-style": 1, - "border-top": 1, - "border-top-width": 1, - "border-width": 1, - - "clear": 1, - "color": 1, - "display": 1, - "float": 1, - - "font": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - - "height": 1, - "letter-spacing": 1, - "line-height": 1, - - "list-style": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - - "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, - - "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, - - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - - "vertical-align": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1 - -}; \ No newline at end of file diff --git a/src/css/Level2Properties.js b/src/css/Level2Properties.js deleted file mode 100644 index 73eabb5b..00000000 --- a/src/css/Level2Properties.js +++ /dev/null @@ -1,109 +0,0 @@ - -var Level2Properties = { - - //Aural - "azimuth": 1, - "cue-after": 1, - "cue-before": 1, - "cue": 1, - "elevation": 1, - "pause-after": 1, - "pause-before": 1, - "pause": 1, - "pitch-range": 1, - "pitch": 1, - "play-during": 1, - "richness": 1, - "speak-header": 1, - "speak-numeral": 1, - "speak-punctuation": 1, - "speak": 1, - "speech-rate": 1, - "stress": 1, - "voice-family": 1, - "volume": 1, - - //Paged - "orphans": 1, - "page-break-after": 1, - "page-break-before": 1, - "page-break-inside": 1, - "widows": 1, - - //Interactive - "cursor": 1, - "outline-color": 1, - "outline-style": 1, - "outline-width": 1, - "outline": 1, - - //Visual - "background-attachment": 1, - "background-color": 1, - "background-image": 1, - "background-position": 1, - "background-repeat": 1, - "background": 1, - "border-collapse": 1, - "border-color": 1, - "border-spacing": 1, - "border-style": 1, - "border-top": 1, - "border-top-color": 1, - "border-top-style": 1, - "border-top-width": 1, - "border-width": 1, - "border": 1, - "bottom": 1, - "caption-side": 1, - "clear": 1, - "clip": 1, - "color": 1, - "content": 1, - "counter-increment": 1, - "counter-reset": 1, - "direction": 1, - "display": 1, - "empty-cells": 1, - "float": 1, - "font-family": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - "font": 1, - "height": 1, - "left": 1, - "letter-spacing": 1, - "line-height": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - "list-style": 1, - "margin-right": 1, - "margin-top": 1, - "margin": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, - "min-width": 1, - "overflow": 1, - "padding-top": 1, - "padding": 1, - "position": 1, - "quotes": 1, - "right": 1, - "table-layout": 1, - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-transform": 1, - "top": 1, - "unicode-bidi": 1, - "vertical-align": 1, - "visibility": 1, - "white-space": 1, - "width": 1, - "word-spacing": 1, - "z-index": 1 -}; \ No newline at end of file diff --git a/src/css/Properties.js b/src/css/Properties.js index e2b4780d..1fd41540 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -15,7 +15,7 @@ var Validation = { isIdentifier: function(part, options){ var text = part.text.toString().toLowerCase(), - args = options.split(","), + args = options.split(" | "), i, len, found = false; @@ -36,20 +36,24 @@ var Validation = { return part.type == "integer"; }, + isURI: function(part){ + return part.type == "uri"; + }, + isPercentage: function(part){ return part.type == "percentage" || part == "0"; }, isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto,inherit"); + return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); }, isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin,medium,thick"); + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); }, isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset"); + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, isBorderSideRadius: function(part){ @@ -125,7 +129,14 @@ var Validation = { } }; - +var ValidationType = { + "integer": Validation.isInteger, + "uri": Validation.isURI, + "color": Validation.isColor, + "length": Validation.isLength, + "percentage": Validation.isPercentage, + "measurement": Validation.isMeasurement +}; @@ -135,6 +146,7 @@ var Validation = { var Properties = { + //A "alignment-adjust": 1, "alignment-baseline": 1, "animation": 1, @@ -148,18 +160,18 @@ var Properties = { "animation-timing-function": 1, "appearance": 1, "azimuth": 1, + + //B "backface-visibility": 1, "background": 1, - "background-attachment": function(value){ - Validation.oneIdentifier(value, "scroll,fixed,inherit"); - }, + "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": Validation.oneColorOrTransparent, "background-image": 1, "background-origin": 1, "background-position": 1, - "background-repeat": 1, + "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, "baseline-shift": 1, "binding": 1, @@ -171,14 +183,12 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, - "border-collapse": function(value){ - Validation.oneIdentifier(value, "collapse,separate,inherit"); - }, - "border-color": Validation.oneColorOrTransparent, + "border-bottom-left-radius": Validation.oneBorderSideRadius, + "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-style": Validation.oneBorderStyle, + "border-bottom-width": Validation.oneBorderWidth, + "border-collapse": [ "collapse | separate | inherit" ], + "border-color": Validation.oneColorOrTransparent, "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, @@ -186,14 +196,14 @@ var Properties = { "border-image-source": 1, "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": Validation.oneColorOrTransparent, + "border-left-style": Validation.oneBorderStyle, + "border-left-width": Validation.oneBorderWidth, "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": Validation.oneColorOrTransparent, + "border-right-style": Validation.oneBorderStyle, + "border-right-width": Validation.oneBorderWidth, "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -204,11 +214,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-color": Validation.oneColorOrTransparent, + "border-top-left-radius": Validation.oneBorderSideRadius, + "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-style": Validation.oneBorderStyle, + "border-top-width": Validation.oneBorderWidth, "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -217,11 +227,9 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, + "bottom": Validation.oneMeasurement, "box-align": 1, - "box-decoration-break": function(value){ - Validation.oneIdentifier(value, "slice,clone"); - }, + "box-decoration-break": [ "slice |clone" ], "box-direction": 1, "box-flex": 1, "box-flex-group": 1, @@ -230,20 +238,16 @@ var Properties = { "box-orient": 1, "box-pack": 1, "box-shadow": 1, - "box-sizing": function(value){ - Validation.oneIdentifier(value, "content-box,border-box,inherit"); - }, + "box-sizing": [ "content-box | border-box | inherit" ], "break-after": 1, "break-before": 1, "break-inside": 1, - "caption-side": function(value){ - Validation.oneIdentifier(value, "top,bottom,inherit"); - }, - "clear": function(value){ - Validation.oneIdentifier(value, "none,right,left,both,inherit"); - }, + + //C + "caption-side": [ "top | bottom | inherit" ], + "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": Validation.oneColor, "color-profile": 1, "column-count": 1, "column-fill": 1, @@ -259,18 +263,14 @@ var Properties = { "counter-increment": 1, "counter-reset": 1, "crop": 1, - "cue": function(value){ - Validation.oneIdentifier(value, "cue-after,cue-before,inherit"); - }, + "cue": [ "cue-after | cue-before | inherit" ], "cue-after": 1, "cue-before": 1, "cursor": 1, - "direction": function(value){ - Validation.oneIdentifier(value, "ltr,rtl,inherit"); - }, - "display": function(value){ - Validation.oneIdentifier(value, "inline,block,list-item,inline-block,table,inline-table,table-row-group,table-header-group,table-footer-group,table-row,table-column-group,table-column,table-cell,table-caption,none,inherit"); - }, + + //D + "direction": [ "ltr | rtl | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -278,16 +278,16 @@ var Properties = { "drop-initial-before-align": 1, "drop-initial-size": 1, "drop-initial-value": 1, + + //E "elevation": 1, - "empty-cells": function(value){ - Validation.oneIdentifier(value, "show,hide,inherit"); - }, + "empty-cells": [ "show | hide | inherit" ], + + //F "filter": 1, "fit": 1, "fit-position": 1, - "float": function(value){ - Validation.oneIdentifier(value, "left,right,none,inherit"); - }, + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, @@ -295,48 +295,50 @@ var Properties = { "font-size": 1, "font-size-adjust": 1, "font-stretch": 1, - "font-style": function(value){ - Validation.oneIdentifier(value, "normal,italic,oblique,inherit"); - }, - "font-variant": function(value){ - Validation.oneIdentifier(value, "normal,small-caps,inherit"); - }, - "font-weight": 1, + "font-style": [ "normal | italic | oblique | inherit" ], + "font-variant": [ "normal | small-caps | inherit" ], + "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], + + //G "grid-columns": 1, "grid-rows": 1, + + //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": Validation.oneMeasurement, "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, "hyphenate-lines": 1, "hyphenate-resource": 1, "hyphens": 1, + + //I "icon": 1, "image-orientation": 1, "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, - "left": Validation.oneMeasurement, - "letter-spacing": 1, - "line-height": 1, + + //L + "left": Validation.oneMeasurement, + "letter-spacing": [ "length", "normal | inherit" ], + "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, "line-stacking-strategy": 1, "list-style": 1, - "list-style-image": 1, - "list-style-position": function(value){ - Validation.oneIdentifier(value, "inside,outsider,inherit"); - }, - "list-style-type": function(value){ - Validation.oneIdentifier(value, "disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek,lower-latin,upper-latin,armenian,georgian,lower-alpha,upper-alpha,none,inherit"); - }, + "list-style-image": [ "uri", "none | inherit" ], + "list-style-position": [ "inside | outsider | inherit" ], + "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], + + //M "margin": 1, - "margin-bottom": 1, - "margin-left": 1, - "margin-right": 1, - "margin-top": 1, + "margin-bottom": [ "length", "percentage", "auto | inherit" ], + "margin-left": [ "length", "percentage", "auto | inherit" ], + "margin-right": [ "length", "percentage", "auto | inherit" ], + "margin-top": [ "length", "percentage", "auto | inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -345,46 +347,42 @@ var Properties = { "marquee-play-count": 1, "marquee-speed": 1, "marquee-style": 1, - "max-height": 1, - "max-width": 1, - "min-height": 1, - "min-width": 1, + "max-height": [ "length", "percentage", "none | inherit" ], + "max-width": [ "length", "percentage", "none | inherit" ], + "min-height": [ "length", "percentage", "inherit" ], + "min-width": [ "length", "percentage", "inherit" ], "move-to": 1, + + //N "nav-down": 1, "nav-index": 1, "nav-left": 1, "nav-right": 1, "nav-up": 1, - "opacity": 1, - "orphans": 1, + + //O + "opacity": [ "number", "inherit" ], + "orphans": [ "integer", "inherit" ], "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": [ "color", "invert" ], "outline-offset": 1, - "outline-style": 1, - "outline-width": 1, - "overflow": function(value){ - Validation.oneIdentifier(value, "visible,hidden,scroll,auto,inherit"); - }, + "outline-style": Validation.oneBorderStyle, + "outline-width": Validation.oneBorderWidth, + "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, "overflow-y": 1, + + //P "padding": 1, "padding-bottom": 1, "padding-left": 1, "padding-right": 1, "padding-top": 1, "page": 1, - "page-break-after": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-before": function(value){ - Validation.oneIdentifier(value, "auto,always,avoid,left,right,inherit"); - }, - "page-break-inside": function(value){ - Validation.oneIdentifier(value, "auto,avoid,inherit"); - }, + "page-break-after": [ "auto | always | avoid | left | right | inherit" ], + "page-break-before": [ "auto | always | avoid | left | right | inherit" ], + "page-break-inside": [ "auto | avoid | inherit" ], "page-policy": 1, "pause": 1, "pause-after": 1, @@ -395,63 +393,56 @@ var Properties = { "pitch": 1, "pitch-range": 1, "play-during": 1, - "position": function(value){ - Validation.oneIdentifier(value, "static,relative,absolute,fixed,inherit"); - }, + "position": [ "static | relative | absolute | fixed | inherit" ], "presentation-level": 1, "punctuation-trim": 1, + + //Q "quotes": 1, + + //R "rendering-intent": 1, "resize": 1, "rest": 1, "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": Validation.oneMeasurement, "rotation": 1, "rotation-point": 1, "ruby-align": 1, "ruby-overhang": 1, "ruby-position": 1, "ruby-span": 1, + + //S "size": 1, - "speak": function(value){ - Validation.oneIdentifier(value, "normal,none,spell-out,inherit"); - }, - "speak-header": function(value){ - Validation.oneIdentifier(value, "once,always,inherit"); - }, - "speak-numeral": function(value){ - Validation.oneIdentifier(value, "digits,continuous,inherit"); - }, - "speak-punctuation": function(value){ - Validation.oneIdentifier(value, "code,none,inherit"); - }, + "speak": [ "normal | none | spell-out | inherit" ], + "speak-header": [ "once | always | inherit" ], + "speak-numeral": [ "digits | continuous | inherit" ], + "speak-punctuation": [ "code | none | inherit" ], "speech-rate": 1, "src" : 1, "stress": 1, "string-set": 1, - "table-layout": 1, + + "table-layout": [ "auto | fixed | inherit" ], "target": 1, "target-name": 1, "target-new": 1, "target-position": 1, - "text-align": function(value){ - Validation.oneIdentifier(value, "left,right,center,justify,inherit"); - }, + "text-align": [ "left | right | center | justify | inherit" ], "text-align-last": 1, "text-decoration": 1, "text-emphasis": 1, "text-height": 1, - "text-indent": 1, + "text-indent": [ "length", "percentage", "inherit" ], "text-justify": 1, "text-outline": 1, "text-shadow": 1, - "text-transform": function(value){ - Validation.oneIdentifier(value, "capitalize,uppercase,lowercase,none,inherit"); - }, + "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": Validation.oneMeasurement, "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -460,19 +451,15 @@ var Properties = { "transition-duration": 1, "transition-property": 1, "transition-timing-function": 1, - "unicode-bidi": function(value){ - Validation.oneIdentifier(value, "normal,embed,bidi-override,inherit"); - }, - "user-modify": function(value){ - Validation.oneIdentifier(value, "read-only,read-write,write-only,inherit"); - }, - "user-select": function(value){ - Validation.oneIdentifier(value, "none,text,toggle,element,elements,all,inherit"); - }, - "vertical-align": 1, - "visibility": function(value){ - Validation.oneIdentifier(value, "visible,hidden,collapse,inherit"); - }, + + //U + "unicode-bidi": [ "normal | embed | bidi-override | inherit" ], + "user-modify": [ "read-only | read-write | write-only | inherit" ], + "user-select": [ "none | text | toggle | element | elements | all | inherit" ], + + //V + "vertical-align": [ "percentage", "length", "baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit" ], + "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, "voice-family": 1, @@ -482,26 +469,51 @@ var Properties = { "voice-stress": 1, "voice-volume": 1, "volume": 1, - "white-space": function(value){ - Validation.oneIdentifier(value, "normal,pre,nowrap,pre-wrap,pre-line,inherit"); - }, + + //W + "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, - "widows": 1, - "width": Validation.oneMeasurement, + "widows": [ "integer", "inherit" ], + "width": [ "measurement" ], "word-break": 1, - "word-spacing": function(value){ - Validation.oneValue(value); - if (!Validation.isLength(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "normal,inherit")){ - throw new ValidationError("Expected a measurement or one of 'normal,inherit' but found '" + value + "'.", value.line, value.col); - } - }, - + "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, - "z-index": function(value){ - Validation.oneValue(value); - if (!Validation.isInteger(value.parts[0]) && !Validation.isIdentifier(value.parts[0], "auto,inherit")){ - throw new ValidationError("Expected an integer or one of 'auto,inherit' but found '" + value + "'.", value.line, value.col); - } - }, + + //Z + "z-index": [ "integer", "auto | inherit" ], "zoom": 1 -}; \ No newline at end of file +}; + +//Create validation functions for strings +(function(){ + var prop; + for (prop in Properties){ + if (Properties.hasOwnProperty(prop)){ + if (Properties[prop] instanceof Array){ + Properties[prop] = (function(values){ + return function(value){ + var valid = false, + msg = [], + part = value.parts[0]; + + Validation.oneValue(value); + + for (var i=0, len=values.length; i < len && !valid; i++){ + if (typeof ValidationType[values[i]] == "undefined"){ + valid = valid || Validation.isIdentifier(part, values[i]); + msg.push("one of (" + values[i] + ")"); + } else { + valid = valid || ValidationType[values[i]](part); + msg.push(values[i]); + } + } + + if (!valid){ + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); + } + }; + })(Properties[prop]); + } + } + } +})(); \ No newline at end of file diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index a3e73fa2..3da86405 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1502,7 +1502,7 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected one of (scroll,fixed,inherit) but found 'foo'.", event.invalid.message); + assert.areEqual("Expected one of (scroll | fixed | inherit) but found 'foo'.", event.invalid.message); }); var result = parser.parse(".foo { background-attachment: foo; }"); }, @@ -1511,7 +1511,7 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected an integer or one of 'auto,inherit' but found 'foo'.", event.invalid.message); + assert.areEqual("Expected integer or one of (auto | inherit) but found 'foo'.", event.invalid.message); }); var result = parser.parse(".foo { z-index: foo; }"); }, @@ -1598,9 +1598,42 @@

CSS Parser Tests

}, - + testMinHeight1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1px; }"); + + }, + testMinHeight2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1%; }"); + + }, + testMinHeight3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: inherit; }"); + + }, + + testInvalidMinHeight: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected length or percentage or one of (inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { min-height: foo}"); + + } From b9a1025d5de520d8e9cbcb38ab475495e2d3a6ba Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 20 Oct 2011 14:53:40 -0700 Subject: [PATCH 013/313] Added a bunch of validation for CSS properties --- build/node-parserlib.js | 217 +++++++++++++++++++++++------------ build/parserlib-core.js | 2 +- build/parserlib-css.js | 215 ++++++++++++++++++++++------------ build/parserlib.js | 217 +++++++++++++++++++++++------------ src/css/Properties.js | 199 +++++++++++++++++++++----------- tests/css/CSSParserTests.htm | 14 +-- 6 files changed, 566 insertions(+), 298 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 6c5bcc97..3573b0a6 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3503,12 +3503,73 @@ var Validation = { }; var ValidationType = { - "integer": Validation.isInteger, - "uri": Validation.isURI, - "color": Validation.isColor, - "length": Validation.isLength, - "percentage": Validation.isPercentage, - "measurement": Validation.isMeasurement + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } }; @@ -3540,7 +3601,7 @@ var Properties = { "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": [ "color", "inherit" ], "background-image": 1, "background-origin": 1, "background-position": 1, @@ -3558,25 +3619,25 @@ var Properties = { "border-bottom-color": 1, "border-bottom-left-radius": Validation.oneBorderSideRadius, "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, + "border-bottom-style": [ "border-style" ], + "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": Validation.oneColorOrTransparent, + "border-color": [ "color", "inherit" ], "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, "border-image-slice": 1, - "border-image-source": 1, + "border-image-source": [ "image", "none" ], "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": [ "color", "inherit" ], + "border-left-style": [ "border-style" ], + "border-left-width": [ "border-width" ], "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": [ "color", "inherit" ], + "border-right-style": [ "border-style" ], + "border-right-width": [ "border-width" ], "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -3587,11 +3648,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, + "border-top-color": [ "color", "inherit" ], "border-top-left-radius": Validation.oneBorderSideRadius, "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-style": [ "border-style" ], + "border-top-width": [ "border-width" ], "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -3600,37 +3661,37 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, - "box-align": 1, + "bottom": [ "margin-width", "inherit" ], + "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], - "box-direction": 1, - "box-flex": 1, - "box-flex-group": 1, - "box-lines": 1, - "box-ordinal-group": 1, - "box-orient": 1, - "box-pack": 1, + "box-direction": [ "normal | reverse | inherit" ], + "box-flex": [ "number" ], + "box-flex-group": [ "integer" ], + "box-lines": [ "single | multiple" ], + "box-ordinal-group": [ "integer" ], + "box-orient": [ "horizontal | vertical | inline-axis | block-axis | inherit" ], + "box-pack": [ "start | end | center | justify" ], "box-shadow": 1, "box-sizing": [ "content-box | border-box | inherit" ], - "break-after": 1, - "break-before": 1, - "break-inside": 1, + "break-after": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-before": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-inside": [ "auto | avoid | avoid-page | avoid-column" ], //C "caption-side": [ "top | bottom | inherit" ], "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": [ "color", "inherit" ], "color-profile": 1, - "column-count": 1, - "column-fill": 1, - "column-gap": 1, + "column-count": [ "integer", "auto" ], //http://www.w3.org/TR/css3-multicol/ + "column-fill": [ "auto | balance" ], + "column-gap": [ "length", "normal" ], "column-rule": 1, - "column-rule-color": 1, - "column-rule-style": 1, - "column-rule-width": 1, - "column-span": 1, - "column-width": 1, + "column-rule-color": [ "color" ], + "column-rule-style": [ "border-style" ], + "column-rule-width": [ "border-width" ], + "column-span": [ "none | all" ], + "column-width": [ "length", "auto" ], "columns": 1, "content": 1, "counter-increment": 1, @@ -3643,7 +3704,7 @@ var Properties = { //D "direction": [ "ltr | rtl | inherit" ], - "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid", "none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3658,14 +3719,13 @@ var Properties = { //F "filter": 1, - "fit": 1, + "fit": [ "fill | hidden | meet | slice" ], "fit-position": 1, - "float": [ "left | right | none | inherit" ], - + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, "font-family": 1, - "font-size": 1, + "font-size": [ "absolute-size", "relative-size", "length", "percentage", "inherit" ], "font-size-adjust": 1, "font-stretch": 1, "font-style": [ "normal | italic | oblique | inherit" ], @@ -3673,12 +3733,23 @@ var Properties = { "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], //G + "grid-cell-stacking": [ "columns | rows | layer" ], + "grid-column": 1, "grid-columns": 1, + "grid-column-align": [ "start | end | center | stretch" ], + "grid-column-sizing": 1, + "grid-column-span": [ "integer" ], + "grid-flow": [ "none | rows | columns" ], + "grid-layer": [ "integer" ], + "grid-row": 1, "grid-rows": 1, + "grid-row-align": [ "start | end | center | stretch" ], + "grid-row-span": [ "integer" ], + "grid-row-sizing": 1, //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -3688,13 +3759,13 @@ var Properties = { //I "icon": 1, - "image-orientation": 1, + "image-orientation": [ "angle", "auto" ], "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, //L - "left": Validation.oneMeasurement, + "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, @@ -3708,10 +3779,10 @@ var Properties = { //M "margin": 1, - "margin-bottom": [ "length", "percentage", "auto | inherit" ], - "margin-left": [ "length", "percentage", "auto | inherit" ], - "margin-right": [ "length", "percentage", "auto | inherit" ], - "margin-top": [ "length", "percentage", "auto | inherit" ], + "margin-bottom": [ "margin-width", "inherit" ], + "margin-left": [ "margin-width", "inherit" ], + "margin-right": [ "margin-width", "inherit" ], + "margin-top": [ "margin-width", "inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -3723,7 +3794,7 @@ var Properties = { "max-height": [ "length", "percentage", "none | inherit" ], "max-width": [ "length", "percentage", "none | inherit" ], "min-height": [ "length", "percentage", "inherit" ], - "min-width": 1, + "min-width": [ "length", "percentage", "inherit" ], "move-to": 1, //N @@ -3734,15 +3805,13 @@ var Properties = { "nav-up": 1, //O - "opacity": 1, - "orphans": 1, + "opacity": [ "number", "inherit" ], + "orphans": [ "integer", "inherit" ], "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": [ "color", "invert | inherit" ], "outline-offset": 1, - "outline-style": 1, - "outline-width": 1, + "outline-style": [ "border-style", "inherit" ], + "outline-width": [ "border-width", "inherit" ], "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, @@ -3750,10 +3819,10 @@ var Properties = { //P "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, + "padding-bottom": [ "padding-width", "inherit" ], + "padding-left": [ "padding-width", "inherit" ], + "padding-right": [ "padding-width", "inherit" ], + "padding-top": [ "padding-width", "inherit" ], "page": 1, "page-break-after": [ "auto | always | avoid | left | right | inherit" ], "page-break-before": [ "auto | always | avoid | left | right | inherit" ], @@ -3782,7 +3851,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": [ "margin-width", "inherit" ], "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -3811,13 +3880,13 @@ var Properties = { "text-decoration": 1, "text-emphasis": 1, "text-height": 1, - "text-indent": 1, + "text-indent": [ "length", "percentage", "inherit" ], "text-justify": 1, "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -3833,7 +3902,7 @@ var Properties = { "user-select": [ "none | text | toggle | element | elements | all | inherit" ], //V - "vertical-align": 1, + "vertical-align": [ "percentage", "length", "baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit" ], "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, @@ -3848,8 +3917,8 @@ var Properties = { //W "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, - "widows": 1, - "width": [ "measurement" ], + "widows": [ "integer", "inherit" ], + "width": [ "length", "percentage", "auto", "inherit" ], "word-break": 1, "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, @@ -3875,7 +3944,7 @@ var Properties = { for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || Validation.isIdentifier(part, values[i]); + valid = valid || ValidationType.identifier(part, values[i]); msg.push("one of (" + values[i] + ")"); } else { valid = valid || ValidationType[values[i]](part); diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 8c82e116..3744157a 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index d6f944e5..26e40d12 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2594,12 +2594,73 @@ var Validation = { }; var ValidationType = { - "integer": Validation.isInteger, - "uri": Validation.isURI, - "color": Validation.isColor, - "length": Validation.isLength, - "percentage": Validation.isPercentage, - "measurement": Validation.isMeasurement + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } }; @@ -2631,7 +2692,7 @@ var Properties = { "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": [ "color", "inherit" ], "background-image": 1, "background-origin": 1, "background-position": 1, @@ -2649,25 +2710,25 @@ var Properties = { "border-bottom-color": 1, "border-bottom-left-radius": Validation.oneBorderSideRadius, "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, + "border-bottom-style": [ "border-style" ], + "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": Validation.oneColorOrTransparent, + "border-color": [ "color", "inherit" ], "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, "border-image-slice": 1, - "border-image-source": 1, + "border-image-source": [ "image", "none" ], "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": [ "color", "inherit" ], + "border-left-style": [ "border-style" ], + "border-left-width": [ "border-width" ], "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": [ "color", "inherit" ], + "border-right-style": [ "border-style" ], + "border-right-width": [ "border-width" ], "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -2678,11 +2739,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, + "border-top-color": [ "color", "inherit" ], "border-top-left-radius": Validation.oneBorderSideRadius, "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-style": [ "border-style" ], + "border-top-width": [ "border-width" ], "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -2691,37 +2752,37 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, - "box-align": 1, + "bottom": [ "margin-width", "inherit" ], + "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], - "box-direction": 1, - "box-flex": 1, - "box-flex-group": 1, - "box-lines": 1, - "box-ordinal-group": 1, - "box-orient": 1, - "box-pack": 1, + "box-direction": [ "normal | reverse | inherit" ], + "box-flex": [ "number" ], + "box-flex-group": [ "integer" ], + "box-lines": [ "single | multiple" ], + "box-ordinal-group": [ "integer" ], + "box-orient": [ "horizontal | vertical | inline-axis | block-axis | inherit" ], + "box-pack": [ "start | end | center | justify" ], "box-shadow": 1, "box-sizing": [ "content-box | border-box | inherit" ], - "break-after": 1, - "break-before": 1, - "break-inside": 1, + "break-after": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-before": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-inside": [ "auto | avoid | avoid-page | avoid-column" ], //C "caption-side": [ "top | bottom | inherit" ], "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": [ "color", "inherit" ], "color-profile": 1, - "column-count": 1, - "column-fill": 1, - "column-gap": 1, + "column-count": [ "integer", "auto" ], //http://www.w3.org/TR/css3-multicol/ + "column-fill": [ "auto | balance" ], + "column-gap": [ "length", "normal" ], "column-rule": 1, - "column-rule-color": 1, - "column-rule-style": 1, - "column-rule-width": 1, - "column-span": 1, - "column-width": 1, + "column-rule-color": [ "color" ], + "column-rule-style": [ "border-style" ], + "column-rule-width": [ "border-width" ], + "column-span": [ "none | all" ], + "column-width": [ "length", "auto" ], "columns": 1, "content": 1, "counter-increment": 1, @@ -2734,7 +2795,7 @@ var Properties = { //D "direction": [ "ltr | rtl | inherit" ], - "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid", "none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -2749,14 +2810,13 @@ var Properties = { //F "filter": 1, - "fit": 1, + "fit": [ "fill | hidden | meet | slice" ], "fit-position": 1, - "float": [ "left | right | none | inherit" ], - + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, "font-family": 1, - "font-size": 1, + "font-size": [ "absolute-size", "relative-size", "length", "percentage", "inherit" ], "font-size-adjust": 1, "font-stretch": 1, "font-style": [ "normal | italic | oblique | inherit" ], @@ -2764,12 +2824,23 @@ var Properties = { "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], //G + "grid-cell-stacking": [ "columns | rows | layer" ], + "grid-column": 1, "grid-columns": 1, + "grid-column-align": [ "start | end | center | stretch" ], + "grid-column-sizing": 1, + "grid-column-span": [ "integer" ], + "grid-flow": [ "none | rows | columns" ], + "grid-layer": [ "integer" ], + "grid-row": 1, "grid-rows": 1, + "grid-row-align": [ "start | end | center | stretch" ], + "grid-row-span": [ "integer" ], + "grid-row-sizing": 1, //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -2779,13 +2850,13 @@ var Properties = { //I "icon": 1, - "image-orientation": 1, + "image-orientation": [ "angle", "auto" ], "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, //L - "left": Validation.oneMeasurement, + "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, @@ -2799,10 +2870,10 @@ var Properties = { //M "margin": 1, - "margin-bottom": [ "length", "percentage", "auto | inherit" ], - "margin-left": [ "length", "percentage", "auto | inherit" ], - "margin-right": [ "length", "percentage", "auto | inherit" ], - "margin-top": [ "length", "percentage", "auto | inherit" ], + "margin-bottom": [ "margin-width", "inherit" ], + "margin-left": [ "margin-width", "inherit" ], + "margin-right": [ "margin-width", "inherit" ], + "margin-top": [ "margin-width", "inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -2814,7 +2885,7 @@ var Properties = { "max-height": [ "length", "percentage", "none | inherit" ], "max-width": [ "length", "percentage", "none | inherit" ], "min-height": [ "length", "percentage", "inherit" ], - "min-width": 1, + "min-width": [ "length", "percentage", "inherit" ], "move-to": 1, //N @@ -2825,15 +2896,13 @@ var Properties = { "nav-up": 1, //O - "opacity": 1, - "orphans": 1, + "opacity": [ "number", "inherit" ], + "orphans": [ "integer", "inherit" ], "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": [ "color", "invert | inherit" ], "outline-offset": 1, - "outline-style": 1, - "outline-width": 1, + "outline-style": [ "border-style", "inherit" ], + "outline-width": [ "border-width", "inherit" ], "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, @@ -2841,10 +2910,10 @@ var Properties = { //P "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, + "padding-bottom": [ "padding-width", "inherit" ], + "padding-left": [ "padding-width", "inherit" ], + "padding-right": [ "padding-width", "inherit" ], + "padding-top": [ "padding-width", "inherit" ], "page": 1, "page-break-after": [ "auto | always | avoid | left | right | inherit" ], "page-break-before": [ "auto | always | avoid | left | right | inherit" ], @@ -2873,7 +2942,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": [ "margin-width", "inherit" ], "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -2902,13 +2971,13 @@ var Properties = { "text-decoration": 1, "text-emphasis": 1, "text-height": 1, - "text-indent": 1, + "text-indent": [ "length", "percentage", "inherit" ], "text-justify": 1, "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -2924,7 +2993,7 @@ var Properties = { "user-select": [ "none | text | toggle | element | elements | all | inherit" ], //V - "vertical-align": 1, + "vertical-align": [ "percentage", "length", "baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit" ], "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, @@ -2939,8 +3008,8 @@ var Properties = { //W "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, - "widows": 1, - "width": [ "measurement" ], + "widows": [ "integer", "inherit" ], + "width": [ "length", "percentage", "auto", "inherit" ], "word-break": 1, "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, @@ -2966,7 +3035,7 @@ var Properties = { for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || Validation.isIdentifier(part, values[i]); + valid = valid || ValidationType.identifier(part, values[i]); msg.push("one of (" + values[i] + ")"); } else { valid = valid || ValidationType[values[i]](part); diff --git a/build/parserlib.js b/build/parserlib.js index d53ee617..f4b278eb 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 12:57:45 */ +/* Build time: 20-October-2011 02:53:22 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3503,12 +3503,73 @@ var Validation = { }; var ValidationType = { - "integer": Validation.isInteger, - "uri": Validation.isURI, - "color": Validation.isColor, - "length": Validation.isLength, - "percentage": Validation.isPercentage, - "measurement": Validation.isMeasurement + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } }; @@ -3540,7 +3601,7 @@ var Properties = { "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": [ "color", "inherit" ], "background-image": 1, "background-origin": 1, "background-position": 1, @@ -3558,25 +3619,25 @@ var Properties = { "border-bottom-color": 1, "border-bottom-left-radius": Validation.oneBorderSideRadius, "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, + "border-bottom-style": [ "border-style" ], + "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": Validation.oneColorOrTransparent, + "border-color": [ "color", "inherit" ], "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, "border-image-slice": 1, - "border-image-source": 1, + "border-image-source": [ "image", "none" ], "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": [ "color", "inherit" ], + "border-left-style": [ "border-style" ], + "border-left-width": [ "border-width" ], "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": [ "color", "inherit" ], + "border-right-style": [ "border-style" ], + "border-right-width": [ "border-width" ], "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -3587,11 +3648,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, + "border-top-color": [ "color", "inherit" ], "border-top-left-radius": Validation.oneBorderSideRadius, "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-style": [ "border-style" ], + "border-top-width": [ "border-width" ], "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -3600,37 +3661,37 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, - "box-align": 1, + "bottom": [ "margin-width", "inherit" ], + "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], - "box-direction": 1, - "box-flex": 1, - "box-flex-group": 1, - "box-lines": 1, - "box-ordinal-group": 1, - "box-orient": 1, - "box-pack": 1, + "box-direction": [ "normal | reverse | inherit" ], + "box-flex": [ "number" ], + "box-flex-group": [ "integer" ], + "box-lines": [ "single | multiple" ], + "box-ordinal-group": [ "integer" ], + "box-orient": [ "horizontal | vertical | inline-axis | block-axis | inherit" ], + "box-pack": [ "start | end | center | justify" ], "box-shadow": 1, "box-sizing": [ "content-box | border-box | inherit" ], - "break-after": 1, - "break-before": 1, - "break-inside": 1, + "break-after": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-before": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-inside": [ "auto | avoid | avoid-page | avoid-column" ], //C "caption-side": [ "top | bottom | inherit" ], "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": [ "color", "inherit" ], "color-profile": 1, - "column-count": 1, - "column-fill": 1, - "column-gap": 1, + "column-count": [ "integer", "auto" ], //http://www.w3.org/TR/css3-multicol/ + "column-fill": [ "auto | balance" ], + "column-gap": [ "length", "normal" ], "column-rule": 1, - "column-rule-color": 1, - "column-rule-style": 1, - "column-rule-width": 1, - "column-span": 1, - "column-width": 1, + "column-rule-color": [ "color" ], + "column-rule-style": [ "border-style" ], + "column-rule-width": [ "border-width" ], + "column-span": [ "none | all" ], + "column-width": [ "length", "auto" ], "columns": 1, "content": 1, "counter-increment": 1, @@ -3643,7 +3704,7 @@ var Properties = { //D "direction": [ "ltr | rtl | inherit" ], - "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid", "none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -3658,14 +3719,13 @@ var Properties = { //F "filter": 1, - "fit": 1, + "fit": [ "fill | hidden | meet | slice" ], "fit-position": 1, - "float": [ "left | right | none | inherit" ], - + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, "font-family": 1, - "font-size": 1, + "font-size": [ "absolute-size", "relative-size", "length", "percentage", "inherit" ], "font-size-adjust": 1, "font-stretch": 1, "font-style": [ "normal | italic | oblique | inherit" ], @@ -3673,12 +3733,23 @@ var Properties = { "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], //G + "grid-cell-stacking": [ "columns | rows | layer" ], + "grid-column": 1, "grid-columns": 1, + "grid-column-align": [ "start | end | center | stretch" ], + "grid-column-sizing": 1, + "grid-column-span": [ "integer" ], + "grid-flow": [ "none | rows | columns" ], + "grid-layer": [ "integer" ], + "grid-row": 1, "grid-rows": 1, + "grid-row-align": [ "start | end | center | stretch" ], + "grid-row-span": [ "integer" ], + "grid-row-sizing": 1, //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -3688,13 +3759,13 @@ var Properties = { //I "icon": 1, - "image-orientation": 1, + "image-orientation": [ "angle", "auto" ], "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, //L - "left": Validation.oneMeasurement, + "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, @@ -3708,10 +3779,10 @@ var Properties = { //M "margin": 1, - "margin-bottom": [ "length", "percentage", "auto | inherit" ], - "margin-left": [ "length", "percentage", "auto | inherit" ], - "margin-right": [ "length", "percentage", "auto | inherit" ], - "margin-top": [ "length", "percentage", "auto | inherit" ], + "margin-bottom": [ "margin-width", "inherit" ], + "margin-left": [ "margin-width", "inherit" ], + "margin-right": [ "margin-width", "inherit" ], + "margin-top": [ "margin-width", "inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -3723,7 +3794,7 @@ var Properties = { "max-height": [ "length", "percentage", "none | inherit" ], "max-width": [ "length", "percentage", "none | inherit" ], "min-height": [ "length", "percentage", "inherit" ], - "min-width": 1, + "min-width": [ "length", "percentage", "inherit" ], "move-to": 1, //N @@ -3734,15 +3805,13 @@ var Properties = { "nav-up": 1, //O - "opacity": 1, - "orphans": 1, + "opacity": [ "number", "inherit" ], + "orphans": [ "integer", "inherit" ], "outline": 1, - "outline-color": function(value){ - Validation.oneColor(value, "invert"); - }, + "outline-color": [ "color", "invert | inherit" ], "outline-offset": 1, - "outline-style": 1, - "outline-width": 1, + "outline-style": [ "border-style", "inherit" ], + "outline-width": [ "border-width", "inherit" ], "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, @@ -3750,10 +3819,10 @@ var Properties = { //P "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, + "padding-bottom": [ "padding-width", "inherit" ], + "padding-left": [ "padding-width", "inherit" ], + "padding-right": [ "padding-width", "inherit" ], + "padding-top": [ "padding-width", "inherit" ], "page": 1, "page-break-after": [ "auto | always | avoid | left | right | inherit" ], "page-break-before": [ "auto | always | avoid | left | right | inherit" ], @@ -3782,7 +3851,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": [ "margin-width", "inherit" ], "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -3811,13 +3880,13 @@ var Properties = { "text-decoration": 1, "text-emphasis": 1, "text-height": 1, - "text-indent": 1, + "text-indent": [ "length", "percentage", "inherit" ], "text-justify": 1, "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -3833,7 +3902,7 @@ var Properties = { "user-select": [ "none | text | toggle | element | elements | all | inherit" ], //V - "vertical-align": 1, + "vertical-align": [ "percentage", "length", "baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit" ], "visibility": [ "visible | hidden | collapse | inherit" ], "voice-balance": 1, "voice-duration": 1, @@ -3848,8 +3917,8 @@ var Properties = { //W "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, - "widows": 1, - "width": [ "measurement" ], + "widows": [ "integer", "inherit" ], + "width": [ "length", "percentage", "auto", "inherit" ], "word-break": 1, "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, @@ -3875,7 +3944,7 @@ var Properties = { for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || Validation.isIdentifier(part, values[i]); + valid = valid || ValidationType.identifier(part, values[i]); msg.push("one of (" + values[i] + ")"); } else { valid = valid || ValidationType[values[i]](part); diff --git a/src/css/Properties.js b/src/css/Properties.js index 1fd41540..20b5d699 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -130,12 +130,73 @@ var Validation = { }; var ValidationType = { - "integer": Validation.isInteger, - "uri": Validation.isURI, - "color": Validation.isColor, - "length": Validation.isLength, - "percentage": Validation.isPercentage, - "measurement": Validation.isMeasurement + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } }; @@ -167,7 +228,7 @@ var Properties = { "background-attachment": [ "scroll | fixed | inherit" ], "background-break": 1, "background-clip": 1, - "background-color": Validation.oneColorOrTransparent, + "background-color": [ "color", "inherit" ], "background-image": 1, "background-origin": 1, "background-position": 1, @@ -185,25 +246,25 @@ var Properties = { "border-bottom-color": 1, "border-bottom-left-radius": Validation.oneBorderSideRadius, "border-bottom-right-radius": Validation.oneBorderSideRadius, - "border-bottom-style": Validation.oneBorderStyle, - "border-bottom-width": Validation.oneBorderWidth, + "border-bottom-style": [ "border-style" ], + "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": Validation.oneColorOrTransparent, + "border-color": [ "color", "inherit" ], "border-image": 1, "border-image-outset": 1, "border-image-repeat": 1, "border-image-slice": 1, - "border-image-source": 1, + "border-image-source": [ "image", "none" ], "border-image-width": 1, "border-left": 1, - "border-left-color": Validation.oneColorOrTransparent, - "border-left-style": Validation.oneBorderStyle, - "border-left-width": Validation.oneBorderWidth, + "border-left-color": [ "color", "inherit" ], + "border-left-style": [ "border-style" ], + "border-left-width": [ "border-width" ], "border-radius": 1, "border-right": 1, - "border-right-color": Validation.oneColorOrTransparent, - "border-right-style": Validation.oneBorderStyle, - "border-right-width": Validation.oneBorderWidth, + "border-right-color": [ "color", "inherit" ], + "border-right-style": [ "border-style" ], + "border-right-width": [ "border-width" ], "border-spacing": 1, "border-style": function(value){ Validation.maxValues(value, 4); @@ -214,11 +275,11 @@ var Properties = { } }, "border-top": 1, - "border-top-color": Validation.oneColorOrTransparent, + "border-top-color": [ "color", "inherit" ], "border-top-left-radius": Validation.oneBorderSideRadius, "border-top-right-radius": Validation.oneBorderSideRadius, - "border-top-style": Validation.oneBorderStyle, - "border-top-width": Validation.oneBorderWidth, + "border-top-style": [ "border-style" ], + "border-top-width": [ "border-width" ], "border-width": function(value){ Validation.maxValues(value, 4); for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ @@ -227,37 +288,37 @@ var Properties = { } } }, - "bottom": Validation.oneMeasurement, - "box-align": 1, + "bottom": [ "margin-width", "inherit" ], + "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], - "box-direction": 1, - "box-flex": 1, - "box-flex-group": 1, - "box-lines": 1, - "box-ordinal-group": 1, - "box-orient": 1, - "box-pack": 1, + "box-direction": [ "normal | reverse | inherit" ], + "box-flex": [ "number" ], + "box-flex-group": [ "integer" ], + "box-lines": [ "single | multiple" ], + "box-ordinal-group": [ "integer" ], + "box-orient": [ "horizontal | vertical | inline-axis | block-axis | inherit" ], + "box-pack": [ "start | end | center | justify" ], "box-shadow": 1, "box-sizing": [ "content-box | border-box | inherit" ], - "break-after": 1, - "break-before": 1, - "break-inside": 1, + "break-after": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-before": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-inside": [ "auto | avoid | avoid-page | avoid-column" ], //C "caption-side": [ "top | bottom | inherit" ], "clear": [ "none | right | left | both | inherit" ], "clip": 1, - "color": Validation.oneColor, + "color": [ "color", "inherit" ], "color-profile": 1, - "column-count": 1, - "column-fill": 1, - "column-gap": 1, + "column-count": [ "integer", "auto" ], //http://www.w3.org/TR/css3-multicol/ + "column-fill": [ "auto | balance" ], + "column-gap": [ "length", "normal" ], "column-rule": 1, - "column-rule-color": 1, - "column-rule-style": 1, - "column-rule-width": 1, - "column-span": 1, - "column-width": 1, + "column-rule-color": [ "color" ], + "column-rule-style": [ "border-style" ], + "column-rule-width": [ "border-width" ], + "column-span": [ "none | all" ], + "column-width": [ "length", "auto" ], "columns": 1, "content": 1, "counter-increment": 1, @@ -270,7 +331,7 @@ var Properties = { //D "direction": [ "ltr | rtl | inherit" ], - "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid", "none | inherit" ], "dominant-baseline": 1, "drop-initial-after-adjust": 1, "drop-initial-after-align": 1, @@ -285,14 +346,13 @@ var Properties = { //F "filter": 1, - "fit": 1, + "fit": [ "fill | hidden | meet | slice" ], "fit-position": 1, - "float": [ "left | right | none | inherit" ], - + "float": [ "left | right | none | inherit" ], "float-offset": 1, "font": 1, "font-family": 1, - "font-size": 1, + "font-size": [ "absolute-size", "relative-size", "length", "percentage", "inherit" ], "font-size-adjust": 1, "font-stretch": 1, "font-style": [ "normal | italic | oblique | inherit" ], @@ -300,12 +360,23 @@ var Properties = { "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], //G + "grid-cell-stacking": [ "columns | rows | layer" ], + "grid-column": 1, "grid-columns": 1, + "grid-column-align": [ "start | end | center | stretch" ], + "grid-column-sizing": 1, + "grid-column-span": [ "integer" ], + "grid-flow": [ "none | rows | columns" ], + "grid-layer": [ "integer" ], + "grid-row": 1, "grid-rows": 1, + "grid-row-align": [ "start | end | center | stretch" ], + "grid-row-span": [ "integer" ], + "grid-row-sizing": 1, //H "hanging-punctuation": 1, - "height": Validation.oneMeasurement, + "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, "hyphenate-character": 1, @@ -315,13 +386,13 @@ var Properties = { //I "icon": 1, - "image-orientation": 1, + "image-orientation": [ "angle", "auto" ], "image-rendering": 1, "image-resolution": 1, "inline-box-align": 1, //L - "left": Validation.oneMeasurement, + "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], "line-stacking": 1, @@ -335,10 +406,10 @@ var Properties = { //M "margin": 1, - "margin-bottom": [ "length", "percentage", "auto | inherit" ], - "margin-left": [ "length", "percentage", "auto | inherit" ], - "margin-right": [ "length", "percentage", "auto | inherit" ], - "margin-top": [ "length", "percentage", "auto | inherit" ], + "margin-bottom": [ "margin-width", "inherit" ], + "margin-left": [ "margin-width", "inherit" ], + "margin-right": [ "margin-width", "inherit" ], + "margin-top": [ "margin-width", "inherit" ], "mark": 1, "mark-after": 1, "mark-before": 1, @@ -364,10 +435,10 @@ var Properties = { "opacity": [ "number", "inherit" ], "orphans": [ "integer", "inherit" ], "outline": 1, - "outline-color": [ "color", "invert" ], + "outline-color": [ "color", "invert | inherit" ], "outline-offset": 1, - "outline-style": Validation.oneBorderStyle, - "outline-width": Validation.oneBorderWidth, + "outline-style": [ "border-style", "inherit" ], + "outline-width": [ "border-width", "inherit" ], "overflow": [ "visible | hidden | scroll | auto | inherit" ], "overflow-style": 1, "overflow-x": 1, @@ -375,10 +446,10 @@ var Properties = { //P "padding": 1, - "padding-bottom": 1, - "padding-left": 1, - "padding-right": 1, - "padding-top": 1, + "padding-bottom": [ "padding-width", "inherit" ], + "padding-left": [ "padding-width", "inherit" ], + "padding-right": [ "padding-width", "inherit" ], + "padding-top": [ "padding-width", "inherit" ], "page": 1, "page-break-after": [ "auto | always | avoid | left | right | inherit" ], "page-break-before": [ "auto | always | avoid | left | right | inherit" ], @@ -407,7 +478,7 @@ var Properties = { "rest-after": 1, "rest-before": 1, "richness": 1, - "right": Validation.oneMeasurement, + "right": [ "margin-width", "inherit" ], "rotation": 1, "rotation-point": 1, "ruby-align": 1, @@ -442,7 +513,7 @@ var Properties = { "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": 1, - "top": Validation.oneMeasurement, + "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, "transform-style": 1, @@ -474,7 +545,7 @@ var Properties = { "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], "white-space-collapse": 1, "widows": [ "integer", "inherit" ], - "width": [ "measurement" ], + "width": [ "length", "percentage", "auto", "inherit" ], "word-break": 1, "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, @@ -500,7 +571,7 @@ var Properties = { for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || Validation.isIdentifier(part, values[i]); + valid = valid || ValidationType.identifier(part, values[i]); msg.push("one of (" + values[i] + ")"); } else { valid = valid || ValidationType[values[i]](part); diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index 3da86405..26f5c256 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1409,7 +1409,7 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected a color but found 'foo'.", event.invalid.message); + assert.areEqual("Expected color or one of (inherit) but found 'foo'.", event.invalid.message); }); var result = parser.parse(".foo { color: foo; }"); @@ -1419,22 +1419,12 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected a color but found 'invert'.", event.invalid.message); + assert.areEqual("Expected color or one of (inherit) but found 'invert'.", event.invalid.message); }); var result = parser.parse(".foo { color: invert; }"); }, - testInvalidColor3: function(){ - var parser = new Parser({ strict: true}); - parser.addListener("property", function(event){ - assert.isNotNull(event.invalid); - assert.areEqual("Expected a color but found 'transparent'.", event.invalid.message); - }); - var result = parser.parse(".foo { color: transparent; }"); - - }, - testValidColor: function(){ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ From 7465fdd9cd2d8c30520e6e93cb44e21c4b64d429 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 21 Oct 2011 16:49:03 -0700 Subject: [PATCH 014/313] More validation --- build/node-parserlib.js | 183 ++++------------------------------- build/parserlib-core.js | 2 +- build/parserlib-css.js | 181 ++++------------------------------ build/parserlib.js | 183 ++++------------------------------- src/css/Properties.js | 179 ++++------------------------------ tests/css/CSSParserTests.htm | 4 +- 6 files changed, 84 insertions(+), 648 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 3573b0a6..65c7be07 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3371,137 +3371,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -var Validation = { - - isColor: function(part, other){ - var text = part.text.toString().toLowerCase(), - pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; - - if (part.type != "color"){ - if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ - return false; - } - } - - return true; - }, - - isIdentifier: function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - isLength: function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - isInteger: function(part){ - return part.type == "integer"; - }, - - isURI: function(part){ - return part.type == "uri"; - }, - - isPercentage: function(part){ - return part.type == "percentage" || part == "0"; - }, - - isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); - }, - - isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); - }, - - isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - isBorderSideRadius: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part); - }, - - oneValue: function(value){ - var parts = value.parts; - if (parts.length != 1){ - throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); - } - }, - - maxValues: function(value, max){ - var parts = value.parts; - if (parts.length > max){ - throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); - } - }, - - oneColor: function(value, other){ - var part = value.parts[0], - text = part.text.toString().toLowerCase(); - - Validation.oneValue(value); - - if (!Validation.isColor(part, other)){ - throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); - } - }, - - oneColorOrTransparent: function(value){ - Validation.oneColor(value, "transparent"); - }, - - oneIdentifier: function(value, options){ - - Validation.oneValue(value); - - if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ - throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); - } - }, - - oneMeasurement: function(value){ - Validation.oneValue(value); - if (!Validation.isMeasurement(value.parts[0])){ - throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderWidth: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderWidth(value.parts[0])){ - throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderStyle: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderStyle(value.parts[0])){ - throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderSideRadius: function(value){ - Validation.maxValues(value, 2); - for (var i=0, len= value.parts.length; i < len; i++){ - if (!Validation.isBorderSideRadius(value.parts[i])){ - throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); - } - } - } -}; - var ValidationType = { "absolute-size": function(part){ @@ -3556,11 +3425,11 @@ var ValidationType = { }, "border-width": function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + return this.length(part) || this.identifier(part, "thin | medium | thick"); }, "border-style": function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, "margin-width": function(part){ @@ -3617,8 +3486,8 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-left-radius": 1, + "border-bottom-right-radius": 1, "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], @@ -3639,28 +3508,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderStyle(value.parts[i])){ - throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-style": 1, "border-top": 1, "border-top-color": [ "color", "inherit" ], - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-left-radius": 1, + "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderWidth(value.parts[i])){ - throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-width": 1, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -3752,10 +3607,10 @@ var Properties = { "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, - "hyphenate-character": 1, + "hyphenate-character": [ "string", "auto" ], "hyphenate-lines": 1, "hyphenate-resource": 1, - "hyphens": 1, + "hyphens": [ "none | manual | auto" ], //I "icon": 1, @@ -3768,6 +3623,7 @@ var Properties = { "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], + "line-break": [ "auto | loose | normal | strict" ], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, @@ -3871,6 +3727,7 @@ var Properties = { "string-set": 1, "table-layout": [ "auto | fixed | inherit" ], + "tab-size": [ "integer", "length" ], "target": 1, "target-name": 1, "target-new": 1, @@ -3881,11 +3738,11 @@ var Properties = { "text-emphasis": 1, "text-height": 1, "text-indent": [ "length", "percentage", "inherit" ], - "text-justify": 1, + "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], - "text-wrap": 1, + "text-wrap": [ "normal | none | avoid" ], "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, @@ -3919,13 +3776,13 @@ var Properties = { "white-space-collapse": 1, "widows": [ "integer", "inherit" ], "width": [ "length", "percentage", "auto", "inherit" ], - "word-break": 1, + "word-break": [ "normal | keep-all | break-all" ], "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, //Z "z-index": [ "integer", "auto | inherit" ], - "zoom": 1 + "zoom": [ "number", "percentage", "normal" ] }; //Create validation functions for strings @@ -3940,7 +3797,9 @@ var Properties = { msg = [], part = value.parts[0]; - Validation.oneValue(value); + if (value.parts.length != 1){ + throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); + } for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 3744157a..8c7210a1 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 26e40d12..272e544a 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2462,137 +2462,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -var Validation = { - - isColor: function(part, other){ - var text = part.text.toString().toLowerCase(), - pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; - - if (part.type != "color"){ - if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ - return false; - } - } - - return true; - }, - - isIdentifier: function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - isLength: function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - isInteger: function(part){ - return part.type == "integer"; - }, - - isURI: function(part){ - return part.type == "uri"; - }, - - isPercentage: function(part){ - return part.type == "percentage" || part == "0"; - }, - - isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); - }, - - isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); - }, - - isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - isBorderSideRadius: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part); - }, - - oneValue: function(value){ - var parts = value.parts; - if (parts.length != 1){ - throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); - } - }, - - maxValues: function(value, max){ - var parts = value.parts; - if (parts.length > max){ - throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); - } - }, - - oneColor: function(value, other){ - var part = value.parts[0], - text = part.text.toString().toLowerCase(); - - Validation.oneValue(value); - - if (!Validation.isColor(part, other)){ - throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); - } - }, - - oneColorOrTransparent: function(value){ - Validation.oneColor(value, "transparent"); - }, - - oneIdentifier: function(value, options){ - - Validation.oneValue(value); - - if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ - throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); - } - }, - - oneMeasurement: function(value){ - Validation.oneValue(value); - if (!Validation.isMeasurement(value.parts[0])){ - throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderWidth: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderWidth(value.parts[0])){ - throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderStyle: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderStyle(value.parts[0])){ - throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderSideRadius: function(value){ - Validation.maxValues(value, 2); - for (var i=0, len= value.parts.length; i < len; i++){ - if (!Validation.isBorderSideRadius(value.parts[i])){ - throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); - } - } - } -}; - var ValidationType = { "absolute-size": function(part){ @@ -2647,11 +2516,11 @@ var ValidationType = { }, "border-width": function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + return this.length(part) || this.identifier(part, "thin | medium | thick"); }, "border-style": function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, "margin-width": function(part){ @@ -2708,8 +2577,8 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-left-radius": 1, + "border-bottom-right-radius": 1, "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], @@ -2730,28 +2599,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderStyle(value.parts[i])){ - throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-style": 1, "border-top": 1, "border-top-color": [ "color", "inherit" ], - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-left-radius": 1, + "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderWidth(value.parts[i])){ - throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-width": 1, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -2843,10 +2698,10 @@ var Properties = { "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, - "hyphenate-character": 1, + "hyphenate-character": [ "string", "auto" ], "hyphenate-lines": 1, "hyphenate-resource": 1, - "hyphens": 1, + "hyphens": [ "none | manual | auto" ], //I "icon": 1, @@ -2859,6 +2714,7 @@ var Properties = { "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], + "line-break": [ "auto | loose | normal | strict" ], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, @@ -2962,6 +2818,7 @@ var Properties = { "string-set": 1, "table-layout": [ "auto | fixed | inherit" ], + "tab-size": [ "integer", "length" ], "target": 1, "target-name": 1, "target-new": 1, @@ -2972,11 +2829,11 @@ var Properties = { "text-emphasis": 1, "text-height": 1, "text-indent": [ "length", "percentage", "inherit" ], - "text-justify": 1, + "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], - "text-wrap": 1, + "text-wrap": [ "normal | none | avoid" ], "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, @@ -3010,13 +2867,13 @@ var Properties = { "white-space-collapse": 1, "widows": [ "integer", "inherit" ], "width": [ "length", "percentage", "auto", "inherit" ], - "word-break": 1, + "word-break": [ "normal | keep-all | break-all" ], "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, //Z "z-index": [ "integer", "auto | inherit" ], - "zoom": 1 + "zoom": [ "number", "percentage", "normal" ] }; //Create validation functions for strings @@ -3031,7 +2888,9 @@ var Properties = { msg = [], part = value.parts[0]; - Validation.oneValue(value); + if (value.parts.length != 1){ + throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); + } for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ diff --git a/build/parserlib.js b/build/parserlib.js index f4b278eb..5d68c854 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 20-October-2011 02:53:22 */ +/* Build time: 21-October-2011 04:48:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3371,137 +3371,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -var Validation = { - - isColor: function(part, other){ - var text = part.text.toString().toLowerCase(), - pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; - - if (part.type != "color"){ - if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ - return false; - } - } - - return true; - }, - - isIdentifier: function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - isLength: function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - isInteger: function(part){ - return part.type == "integer"; - }, - - isURI: function(part){ - return part.type == "uri"; - }, - - isPercentage: function(part){ - return part.type == "percentage" || part == "0"; - }, - - isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); - }, - - isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); - }, - - isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - isBorderSideRadius: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part); - }, - - oneValue: function(value){ - var parts = value.parts; - if (parts.length != 1){ - throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); - } - }, - - maxValues: function(value, max){ - var parts = value.parts; - if (parts.length > max){ - throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); - } - }, - - oneColor: function(value, other){ - var part = value.parts[0], - text = part.text.toString().toLowerCase(); - - Validation.oneValue(value); - - if (!Validation.isColor(part, other)){ - throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); - } - }, - - oneColorOrTransparent: function(value){ - Validation.oneColor(value, "transparent"); - }, - - oneIdentifier: function(value, options){ - - Validation.oneValue(value); - - if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ - throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); - } - }, - - oneMeasurement: function(value){ - Validation.oneValue(value); - if (!Validation.isMeasurement(value.parts[0])){ - throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderWidth: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderWidth(value.parts[0])){ - throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderStyle: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderStyle(value.parts[0])){ - throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderSideRadius: function(value){ - Validation.maxValues(value, 2); - for (var i=0, len= value.parts.length; i < len; i++){ - if (!Validation.isBorderSideRadius(value.parts[i])){ - throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); - } - } - } -}; - var ValidationType = { "absolute-size": function(part){ @@ -3556,11 +3425,11 @@ var ValidationType = { }, "border-width": function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + return this.length(part) || this.identifier(part, "thin | medium | thick"); }, "border-style": function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, "margin-width": function(part){ @@ -3617,8 +3486,8 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-left-radius": 1, + "border-bottom-right-radius": 1, "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], @@ -3639,28 +3508,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderStyle(value.parts[i])){ - throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-style": 1, "border-top": 1, "border-top-color": [ "color", "inherit" ], - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-left-radius": 1, + "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderWidth(value.parts[i])){ - throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-width": 1, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -3752,10 +3607,10 @@ var Properties = { "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, - "hyphenate-character": 1, + "hyphenate-character": [ "string", "auto" ], "hyphenate-lines": 1, "hyphenate-resource": 1, - "hyphens": 1, + "hyphens": [ "none | manual | auto" ], //I "icon": 1, @@ -3768,6 +3623,7 @@ var Properties = { "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], + "line-break": [ "auto | loose | normal | strict" ], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, @@ -3871,6 +3727,7 @@ var Properties = { "string-set": 1, "table-layout": [ "auto | fixed | inherit" ], + "tab-size": [ "integer", "length" ], "target": 1, "target-name": 1, "target-new": 1, @@ -3881,11 +3738,11 @@ var Properties = { "text-emphasis": 1, "text-height": 1, "text-indent": [ "length", "percentage", "inherit" ], - "text-justify": 1, + "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], - "text-wrap": 1, + "text-wrap": [ "normal | none | avoid" ], "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, @@ -3919,13 +3776,13 @@ var Properties = { "white-space-collapse": 1, "widows": [ "integer", "inherit" ], "width": [ "length", "percentage", "auto", "inherit" ], - "word-break": 1, + "word-break": [ "normal | keep-all | break-all" ], "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, //Z "z-index": [ "integer", "auto | inherit" ], - "zoom": 1 + "zoom": [ "number", "percentage", "normal" ] }; //Create validation functions for strings @@ -3940,7 +3797,9 @@ var Properties = { msg = [], part = value.parts[0]; - Validation.oneValue(value); + if (value.parts.length != 1){ + throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); + } for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ diff --git a/src/css/Properties.js b/src/css/Properties.js index 20b5d699..22f9606c 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -1,134 +1,3 @@ -var Validation = { - - isColor: function(part, other){ - var text = part.text.toString().toLowerCase(), - pattern = "^(?:inherit" + (other ? "|" + other : "") + ")$"; - - if (part.type != "color"){ - if (part.type != "identifier" || !(new RegExp(pattern)).test(text)){ - return false; - } - } - - return true; - }, - - isIdentifier: function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - isLength: function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - isInteger: function(part){ - return part.type == "integer"; - }, - - isURI: function(part){ - return part.type == "uri"; - }, - - isPercentage: function(part){ - return part.type == "percentage" || part == "0"; - }, - - isMeasurement: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part) || Validation.isIdentifier(part, "auto | inherit"); - }, - - isBorderWidth: function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); - }, - - isBorderStyle: function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - isBorderSideRadius: function(part){ - return Validation.isLength(part) || Validation.isPercentage(part); - }, - - oneValue: function(value){ - var parts = value.parts; - if (parts.length != 1){ - throw new ValidationError("Expected one property value but found " + parts.length + ".", value.line, value.col); - } - }, - - maxValues: function(value, max){ - var parts = value.parts; - if (parts.length > max){ - throw new ValidationError("Expected a max of " + max + " property values but found " + parts.length + ".", value.line, value.col); - } - }, - - oneColor: function(value, other){ - var part = value.parts[0], - text = part.text.toString().toLowerCase(); - - Validation.oneValue(value); - - if (!Validation.isColor(part, other)){ - throw new ValidationError("Expected a color but found '" + part + "'.", value.line, value.col); - } - }, - - oneColorOrTransparent: function(value){ - Validation.oneColor(value, "transparent"); - }, - - oneIdentifier: function(value, options){ - - Validation.oneValue(value); - - if (!Validation.isIdentifier.call(Validation, value.parts[0], options)){ - throw new ValidationError("Expected one of (" + options + ") but found '" + value.parts[0] + "'.", value.line, value.col); - } - }, - - oneMeasurement: function(value){ - Validation.oneValue(value); - if (!Validation.isMeasurement(value.parts[0])){ - throw new ValidationError("Expected a measurement but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderWidth: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderWidth(value.parts[0])){ - throw new ValidationError("Expected a border width but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderStyle: function(value){ - Validation.oneValue(value); - if (!Validation.isBorderStyle(value.parts[0])){ - throw new ValidationError("Expected a border style but found '" + value + "'.", value.line, value.col); - } - }, - - oneBorderSideRadius: function(value){ - Validation.maxValues(value, 2); - for (var i=0, len= value.parts.length; i < len; i++){ - if (!Validation.isBorderSideRadius(value.parts[i])){ - throw new ValidationError("Expected a border radius but found '" + value + "'.", value.line, value.col); - } - } - } -}; - var ValidationType = { "absolute-size": function(part){ @@ -183,11 +52,11 @@ var ValidationType = { }, "border-width": function(part){ - return Validation.isLength(part) || Validation.isIdentifier(part, "thin | medium | thick"); + return this.length(part) || this.identifier(part, "thin | medium | thick"); }, "border-style": function(part){ - return Validation.isIdentifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); }, "margin-width": function(part){ @@ -244,8 +113,8 @@ var Properties = { "border": 1, "border-bottom": 1, "border-bottom-color": 1, - "border-bottom-left-radius": Validation.oneBorderSideRadius, - "border-bottom-right-radius": Validation.oneBorderSideRadius, + "border-bottom-left-radius": 1, + "border-bottom-right-radius": 1, "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], @@ -266,28 +135,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderStyle(value.parts[i])){ - throw new ValidationError("Expected a border style but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-style": 1, "border-top": 1, "border-top-color": [ "color", "inherit" ], - "border-top-left-radius": Validation.oneBorderSideRadius, - "border-top-right-radius": Validation.oneBorderSideRadius, + "border-top-left-radius": 1, + "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": function(value){ - Validation.maxValues(value, 4); - for (var i=0, len=Math.min(4,value.parts.length); i < len; i++){ - if (!Validation.isBorderWidth(value.parts[i])){ - throw new ValidationError("Expected a border width but found '" + value.parts[i] + "'.", value.parts[i].line, value.parts[i].col); - } - } - }, + "border-width": 1, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -379,10 +234,10 @@ var Properties = { "height": [ "margin-width", "inherit" ], "hyphenate-after": 1, "hyphenate-before": 1, - "hyphenate-character": 1, + "hyphenate-character": [ "string", "auto" ], "hyphenate-lines": 1, "hyphenate-resource": 1, - "hyphens": 1, + "hyphens": [ "none | manual | auto" ], //I "icon": 1, @@ -395,6 +250,7 @@ var Properties = { "left": [ "margin-width", "inherit" ], "letter-spacing": [ "length", "normal | inherit" ], "line-height": [ "number", "length", "percentage", "normal | inherit"], + "line-break": [ "auto | loose | normal | strict" ], "line-stacking": 1, "line-stacking-ruby": 1, "line-stacking-shift": 1, @@ -498,6 +354,7 @@ var Properties = { "string-set": 1, "table-layout": [ "auto | fixed | inherit" ], + "tab-size": [ "integer", "length" ], "target": 1, "target-name": 1, "target-new": 1, @@ -508,11 +365,11 @@ var Properties = { "text-emphasis": 1, "text-height": 1, "text-indent": [ "length", "percentage", "inherit" ], - "text-justify": 1, + "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], - "text-wrap": 1, + "text-wrap": [ "normal | none | avoid" ], "top": [ "margin-width", "inherit" ], "transform": 1, "transform-origin": 1, @@ -546,13 +403,13 @@ var Properties = { "white-space-collapse": 1, "widows": [ "integer", "inherit" ], "width": [ "length", "percentage", "auto", "inherit" ], - "word-break": 1, + "word-break": [ "normal | keep-all | break-all" ], "word-spacing": [ "length", "normal | inherit" ], "word-wrap": 1, //Z "z-index": [ "integer", "auto | inherit" ], - "zoom": 1 + "zoom": [ "number", "percentage", "normal" ] }; //Create validation functions for strings @@ -567,7 +424,9 @@ var Properties = { msg = [], part = value.parts[0]; - Validation.oneValue(value); + if (value.parts.length != 1){ + throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); + } for (var i=0, len=values.length; i < len && !valid; i++){ if (typeof ValidationType[values[i]] == "undefined"){ diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index 26f5c256..6f020da3 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1567,7 +1567,7 @@

CSS Parser Tests

var result = parser.parse(".foo { border-width: 1px 1px 1px 1px}"); }, - +/* testInvalidBorderWidth1: function(){ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ @@ -1587,7 +1587,7 @@

CSS Parser Tests

var result = parser.parse(".foo { border-width: foo}"); }, - + */ testMinHeight1: function(){ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ From bc4d7355eb2378ec9cf4de60653e759c97417865 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 25 Oct 2011 08:31:06 -0700 Subject: [PATCH 015/313] Fixed number handling in validation --- build/node-parserlib.js | 8 ++++++-- build/parserlib-core.js | 2 +- build/parserlib-css.js | 6 +++++- build/parserlib.js | 8 ++++++-- src/css/Properties.js | 4 ++++ tests/css/CSSParserTests.htm | 10 ++++++++++ 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 65c7be07..e3b9677e 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3404,6 +3404,10 @@ var ValidationType = { return part.type == "color" || part == "transparent"; }, + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + "integer": function(part){ return part.type == "integer"; }, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 8c7210a1..c96342a1 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 272e544a..680c7653 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2495,6 +2495,10 @@ var ValidationType = { return part.type == "color" || part == "transparent"; }, + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + "integer": function(part){ return part.type == "integer"; }, diff --git a/build/parserlib.js b/build/parserlib.js index 5d68c854..e64a5be9 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 21-October-2011 04:48:14 */ +/* Build time: 25-October-2011 08:30:50 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3404,6 +3404,10 @@ var ValidationType = { return part.type == "color" || part == "transparent"; }, + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + "integer": function(part){ return part.type == "integer"; }, diff --git a/src/css/Properties.js b/src/css/Properties.js index 22f9606c..396b1ac7 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -31,6 +31,10 @@ var ValidationType = { return part.type == "color" || part == "transparent"; }, + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + "integer": function(part){ return part.type == "integer"; }, diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index 6f020da3..23f4e110 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1623,7 +1623,17 @@

CSS Parser Tests

}); var result = parser.parse(".foo { min-height: foo}"); + }, + + testOpacity: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { opacity: 1}"); + } + From ba1313c1f8e43f0672f52b21d09decfaad4bc5a9 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 25 Oct 2011 09:12:10 -0700 Subject: [PATCH 016/313] Added multi property value validation --- build/node-parserlib.js | 65 ++++++++++++++++++++++++++++++------ build/parserlib-core.js | 2 +- build/parserlib-css.js | 63 +++++++++++++++++++++++++++++----- build/parserlib.js | 65 ++++++++++++++++++++++++++++++------ src/css/Properties.js | 61 ++++++++++++++++++++++++++++----- tests/css/CSSParserTests.htm | 6 ++-- 6 files changed, 221 insertions(+), 41 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index e3b9677e..cf078a4c 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3495,13 +3495,13 @@ var Properties = { "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": [ "color", "inherit" ], + "border-color": { multi: [ "color", "inherit" ], max: 4 }, "border-image": 1, - "border-image-outset": 1, - "border-image-repeat": 1, + "border-image-outset": { multi: [ "length", "number" ], max: 4 }, + "border-image-repeat": { multi: [ "stretch | repeat | round" ], max: 2 }, "border-image-slice": 1, "border-image-source": [ "image", "none" ], - "border-image-width": 1, + "border-image-width": { multi: [ "length", "percentage", "number", "auto" ], max: 4 }, "border-left": 1, "border-left-color": [ "color", "inherit" ], "border-left-style": [ "border-style" ], @@ -3512,14 +3512,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": 1, + "border-style": { multi: [ "border-style" ], max: 4 }, "border-top": 1, "border-top-color": [ "color", "inherit" ], "border-top-left-radius": 1, "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": 1, + "border-width": { multi: [ "border-width" ], max: 4 }, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -3638,7 +3638,7 @@ var Properties = { "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M - "margin": 1, + "margin": { multi: [ "margin-width", "inherit" ], max: 4 }, "margin-bottom": [ "margin-width", "inherit" ], "margin-left": [ "margin-width", "inherit" ], "margin-right": [ "margin-width", "inherit" ], @@ -3678,7 +3678,7 @@ var Properties = { "overflow-y": 1, //P - "padding": 1, + "padding": { multi: [ "padding-width", "inherit" ], max: 4 }, "padding-bottom": [ "padding-width", "inherit" ], "padding-left": [ "padding-width", "inherit" ], "padding-right": [ "padding-width", "inherit" ], @@ -3820,6 +3820,51 @@ var Properties = { } }; })(Properties[prop]); + } else if (typeof Properties[prop] == "object"){ + Properties[prop] = (function(spec){ + return function(value){ + var valid, + i, len, j, count, + msg, + values, + parts = value.parts; + + if (spec.max) { + if (parts.length > spec.max){ + throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); + } + } + + if (spec.multi){ + values = spec.multi; + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + } + + }; + })(Properties[prop]); } } } diff --git a/build/parserlib-core.js b/build/parserlib-core.js index c96342a1..15e33606 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 680c7653..1392da69 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2586,13 +2586,13 @@ var Properties = { "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": [ "color", "inherit" ], + "border-color": { multi: [ "color", "inherit" ], max: 4 }, "border-image": 1, - "border-image-outset": 1, - "border-image-repeat": 1, + "border-image-outset": { multi: [ "length", "number" ], max: 4 }, + "border-image-repeat": { multi: [ "stretch | repeat | round" ], max: 2 }, "border-image-slice": 1, "border-image-source": [ "image", "none" ], - "border-image-width": 1, + "border-image-width": { multi: [ "length", "percentage", "number", "auto" ], max: 4 }, "border-left": 1, "border-left-color": [ "color", "inherit" ], "border-left-style": [ "border-style" ], @@ -2603,14 +2603,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": 1, + "border-style": { multi: [ "border-style" ], max: 4 }, "border-top": 1, "border-top-color": [ "color", "inherit" ], "border-top-left-radius": 1, "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": 1, + "border-width": { multi: [ "border-width" ], max: 4 }, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -2729,7 +2729,7 @@ var Properties = { "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M - "margin": 1, + "margin": { multi: [ "margin-width", "inherit" ], max: 4 }, "margin-bottom": [ "margin-width", "inherit" ], "margin-left": [ "margin-width", "inherit" ], "margin-right": [ "margin-width", "inherit" ], @@ -2769,7 +2769,7 @@ var Properties = { "overflow-y": 1, //P - "padding": 1, + "padding": { multi: [ "padding-width", "inherit" ], max: 4 }, "padding-bottom": [ "padding-width", "inherit" ], "padding-left": [ "padding-width", "inherit" ], "padding-right": [ "padding-width", "inherit" ], @@ -2911,6 +2911,51 @@ var Properties = { } }; })(Properties[prop]); + } else if (typeof Properties[prop] == "object"){ + Properties[prop] = (function(spec){ + return function(value){ + var valid, + i, len, j, count, + msg, + values, + parts = value.parts; + + if (spec.max) { + if (parts.length > spec.max){ + throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); + } + } + + if (spec.multi){ + values = spec.multi; + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + } + + }; + })(Properties[prop]); } } } diff --git a/build/parserlib.js b/build/parserlib.js index e64a5be9..7b417421 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ var parserlib = {}; (function(){ @@ -930,7 +930,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 08:30:50 */ +/* Build time: 25-October-2011 09:11:57 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3495,13 +3495,13 @@ var Properties = { "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": [ "color", "inherit" ], + "border-color": { multi: [ "color", "inherit" ], max: 4 }, "border-image": 1, - "border-image-outset": 1, - "border-image-repeat": 1, + "border-image-outset": { multi: [ "length", "number" ], max: 4 }, + "border-image-repeat": { multi: [ "stretch | repeat | round" ], max: 2 }, "border-image-slice": 1, "border-image-source": [ "image", "none" ], - "border-image-width": 1, + "border-image-width": { multi: [ "length", "percentage", "number", "auto" ], max: 4 }, "border-left": 1, "border-left-color": [ "color", "inherit" ], "border-left-style": [ "border-style" ], @@ -3512,14 +3512,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": 1, + "border-style": { multi: [ "border-style" ], max: 4 }, "border-top": 1, "border-top-color": [ "color", "inherit" ], "border-top-left-radius": 1, "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": 1, + "border-width": { multi: [ "border-width" ], max: 4 }, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -3638,7 +3638,7 @@ var Properties = { "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M - "margin": 1, + "margin": { multi: [ "margin-width", "inherit" ], max: 4 }, "margin-bottom": [ "margin-width", "inherit" ], "margin-left": [ "margin-width", "inherit" ], "margin-right": [ "margin-width", "inherit" ], @@ -3678,7 +3678,7 @@ var Properties = { "overflow-y": 1, //P - "padding": 1, + "padding": { multi: [ "padding-width", "inherit" ], max: 4 }, "padding-bottom": [ "padding-width", "inherit" ], "padding-left": [ "padding-width", "inherit" ], "padding-right": [ "padding-width", "inherit" ], @@ -3820,6 +3820,51 @@ var Properties = { } }; })(Properties[prop]); + } else if (typeof Properties[prop] == "object"){ + Properties[prop] = (function(spec){ + return function(value){ + var valid, + i, len, j, count, + msg, + values, + parts = value.parts; + + if (spec.max) { + if (parts.length > spec.max){ + throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); + } + } + + if (spec.multi){ + values = spec.multi; + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + } + + }; + })(Properties[prop]); } } } diff --git a/src/css/Properties.js b/src/css/Properties.js index 396b1ac7..20dd7cbe 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -122,13 +122,13 @@ var Properties = { "border-bottom-style": [ "border-style" ], "border-bottom-width": [ "border-width" ], "border-collapse": [ "collapse | separate | inherit" ], - "border-color": [ "color", "inherit" ], + "border-color": { multi: [ "color", "inherit" ], max: 4 }, "border-image": 1, - "border-image-outset": 1, - "border-image-repeat": 1, + "border-image-outset": { multi: [ "length", "number" ], max: 4 }, + "border-image-repeat": { multi: [ "stretch | repeat | round" ], max: 2 }, "border-image-slice": 1, "border-image-source": [ "image", "none" ], - "border-image-width": 1, + "border-image-width": { multi: [ "length", "percentage", "number", "auto" ], max: 4 }, "border-left": 1, "border-left-color": [ "color", "inherit" ], "border-left-style": [ "border-style" ], @@ -139,14 +139,14 @@ var Properties = { "border-right-style": [ "border-style" ], "border-right-width": [ "border-width" ], "border-spacing": 1, - "border-style": 1, + "border-style": { multi: [ "border-style" ], max: 4 }, "border-top": 1, "border-top-color": [ "color", "inherit" ], "border-top-left-radius": 1, "border-top-right-radius": 1, "border-top-style": [ "border-style" ], "border-top-width": [ "border-width" ], - "border-width": 1, + "border-width": { multi: [ "border-width" ], max: 4 }, "bottom": [ "margin-width", "inherit" ], "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ "box-decoration-break": [ "slice |clone" ], @@ -265,7 +265,7 @@ var Properties = { "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M - "margin": 1, + "margin": { multi: [ "margin-width", "inherit" ], max: 4 }, "margin-bottom": [ "margin-width", "inherit" ], "margin-left": [ "margin-width", "inherit" ], "margin-right": [ "margin-width", "inherit" ], @@ -305,7 +305,7 @@ var Properties = { "overflow-y": 1, //P - "padding": 1, + "padding": { multi: [ "padding-width", "inherit" ], max: 4 }, "padding-bottom": [ "padding-width", "inherit" ], "padding-left": [ "padding-width", "inherit" ], "padding-right": [ "padding-width", "inherit" ], @@ -447,6 +447,51 @@ var Properties = { } }; })(Properties[prop]); + } else if (typeof Properties[prop] == "object"){ + Properties[prop] = (function(spec){ + return function(value){ + var valid, + i, len, j, count, + msg, + values, + parts = value.parts; + + if (spec.max) { + if (parts.length > spec.max){ + throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); + } + } + + if (spec.multi){ + values = spec.multi; + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + } + + }; + })(Properties[prop]); } } } diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index 23f4e110..2ba17e21 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1567,7 +1567,7 @@

CSS Parser Tests

var result = parser.parse(".foo { border-width: 1px 1px 1px 1px}"); }, -/* + testInvalidBorderWidth1: function(){ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ @@ -1582,12 +1582,12 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected a border width but found 'foo'.", event.invalid.message); + assert.areEqual("Expected border-width but found 'foo'.", event.invalid.message); }); var result = parser.parse(".foo { border-width: foo}"); }, - */ + testMinHeight1: function(){ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ From 6068b70e4d1248e26f821f20190dfafa5258e6d7 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 31 Oct 2011 11:47:52 -0700 Subject: [PATCH 017/313] Added support for rgba, hsl, and hsla colors --- build/node-parserlib.js | 49 +++++++++++++++++----------------- build/parserlib-core.js | 6 +---- build/parserlib-css.js | 39 ++++++++++++++++----------- build/parserlib.js | 47 +++++++++++++++++---------------- src/css/PropertyValuePart.js | 23 ++++++++++++++++ tests/css/CSSParserTests.htm | 51 ++++++++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 66 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index cf078a4c..f9301596 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,11 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ var parserlib = {}; (function(){ - /** * A generic base to inherit from for any object * that needs event handling. @@ -895,8 +894,6 @@ TokenStreamBase.prototype = { }; - - parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -905,8 +902,6 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); - - /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -930,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -938,7 +933,6 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; - var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -1118,7 +1112,6 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -1150,7 +1143,6 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; - /** * Represents an individual media query. * @namespace parserlib.css @@ -1193,7 +1185,6 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; - /** * A CSS3 parser. * @namespace parserlib.css @@ -3898,7 +3889,6 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; - /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3927,7 +3917,6 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; - /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4035,6 +4024,29 @@ function PropertyValuePart(text, line, col){ this.red = +RegExp.$1 * 255 / 100; this.green = +RegExp.$2 * 255 / 100; this.blue = +RegExp.$3 * 255 / 100; + } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + this.alpha = +RegExp.$4; + } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + this.alpha = +RegExp.$4; + } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl() + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + this.alpha = +RegExp.$4; } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI this.type = "uri"; this.uri = RegExp.$1; @@ -4119,7 +4131,6 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; - /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4161,7 +4172,6 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; - /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4197,7 +4207,6 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; - /** * Represents a selector's specificity. * @namespace parserlib.css @@ -4320,7 +4329,6 @@ Specificity.calculate = function(selector){ }; - var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -5318,7 +5326,6 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); - var Tokens = [ /* @@ -5525,7 +5532,6 @@ var Tokens = [ - /** * Type to use when a validation error occurs. * @class ValidationError @@ -5563,7 +5569,6 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); - parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -5583,12 +5588,8 @@ ValidationError :ValidationError }; })(); - - - (function(){ for(var prop in parserlib){ exports[prop] = parserlib[prop]; } })(); - diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 15e33606..9088a767 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,11 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ var parserlib = {}; (function(){ - /** * A generic base to inherit from for any object * that needs event handling. @@ -895,8 +894,6 @@ TokenStreamBase.prototype = { }; - - parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -905,4 +902,3 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); - diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 1392da69..33df2753 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -29,7 +29,6 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; - var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -209,7 +208,6 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -241,7 +239,6 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; - /** * Represents an individual media query. * @namespace parserlib.css @@ -284,7 +281,6 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; - /** * A CSS3 parser. * @namespace parserlib.css @@ -2989,7 +2985,6 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; - /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3018,7 +3013,6 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; - /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -3126,6 +3120,29 @@ function PropertyValuePart(text, line, col){ this.red = +RegExp.$1 * 255 / 100; this.green = +RegExp.$2 * 255 / 100; this.blue = +RegExp.$3 * 255 / 100; + } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + this.alpha = +RegExp.$4; + } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + this.alpha = +RegExp.$4; + } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl() + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + this.alpha = +RegExp.$4; } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI this.type = "uri"; this.uri = RegExp.$1; @@ -3210,7 +3227,6 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; - /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -3252,7 +3268,6 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; - /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -3288,7 +3303,6 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; - /** * Represents a selector's specificity. * @namespace parserlib.css @@ -3411,7 +3425,6 @@ Specificity.calculate = function(selector){ }; - var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -4409,7 +4422,6 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); - var Tokens = [ /* @@ -4616,7 +4628,6 @@ var Tokens = [ - /** * Type to use when a validation error occurs. * @class ValidationError @@ -4654,7 +4665,6 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); - parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -4673,4 +4683,3 @@ Tokens :Tokens, ValidationError :ValidationError }; })(); - diff --git a/build/parserlib.js b/build/parserlib.js index 7b417421..8a3c197f 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,11 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ var parserlib = {}; (function(){ - /** * A generic base to inherit from for any object * that needs event handling. @@ -895,8 +894,6 @@ TokenStreamBase.prototype = { }; - - parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -905,8 +902,6 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); - - /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -930,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 25-October-2011 09:11:57 */ +/* Build time: 31-October-2011 11:46:10 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -938,7 +933,6 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; - var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -1118,7 +1112,6 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; - /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -1150,7 +1143,6 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; - /** * Represents an individual media query. * @namespace parserlib.css @@ -1193,7 +1185,6 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; - /** * A CSS3 parser. * @namespace parserlib.css @@ -3898,7 +3889,6 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; - /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3927,7 +3917,6 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; - /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4035,6 +4024,29 @@ function PropertyValuePart(text, line, col){ this.red = +RegExp.$1 * 255 / 100; this.green = +RegExp.$2 * 255 / 100; this.blue = +RegExp.$3 * 255 / 100; + } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + this.alpha = +RegExp.$4; + } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + this.alpha = +RegExp.$4; + } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl() + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + this.alpha = +RegExp.$4; } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI this.type = "uri"; this.uri = RegExp.$1; @@ -4119,7 +4131,6 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; - /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4161,7 +4172,6 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; - /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4197,7 +4207,6 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; - /** * Represents a selector's specificity. * @namespace parserlib.css @@ -4320,7 +4329,6 @@ Specificity.calculate = function(selector){ }; - var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, nl = /\n|\r\n|\r|\f/; @@ -5318,7 +5326,6 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } }); - var Tokens = [ /* @@ -5525,7 +5532,6 @@ var Tokens = [ - /** * Type to use when a validation error occurs. * @class ValidationError @@ -5563,7 +5569,6 @@ function ValidationError(message, line, col){ //inherit from Error ValidationError.prototype = new Error(); - parserlib.css = { Colors :Colors, Combinator :Combinator, @@ -5582,5 +5587,3 @@ Tokens :Tokens, ValidationError :ValidationError }; })(); - - diff --git a/src/css/PropertyValuePart.js b/src/css/PropertyValuePart.js index b4467596..f6a4ee84 100644 --- a/src/css/PropertyValuePart.js +++ b/src/css/PropertyValuePart.js @@ -105,6 +105,29 @@ function PropertyValuePart(text, line, col){ this.red = +RegExp.$1 * 255 / 100; this.green = +RegExp.$2 * 255 / 100; this.blue = +RegExp.$3 * 255 / 100; + } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + this.alpha = +RegExp.$4; + } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + this.alpha = +RegExp.$4; + } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl() + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + this.alpha = +RegExp.$4; } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI this.type = "uri"; this.uri = RegExp.$1; diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index 2ba17e21..ba62a6b1 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1055,6 +1055,57 @@

CSS Parser Tests

assert.areEqual(191.25, result.parts[0].blue); }, + testRGBAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(255, 238 , 221, 0.3)"); + + assert.isInstanceOf(parserlib.css.PropertyValue, result); + assert.areEqual(1, result.parts.length); + assert.areEqual("color", result.parts[0].type); + assert.areEqual(255, result.parts[0].red); + assert.areEqual(238, result.parts[0].green); + assert.areEqual(221, result.parts[0].blue); + assert.areEqual(0.3, result.parts[0].alpha); + }, + + testRGBAColorValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(100%,50%, 75%, 0.5)"); + + assert.isInstanceOf(parserlib.css.PropertyValue, result); + assert.areEqual(1, result.parts.length); + assert.areEqual("color", result.parts[0].type); + assert.areEqual(255, result.parts[0].red); + assert.areEqual(127.5, result.parts[0].green); + assert.areEqual(191.25, result.parts[0].blue); + assert.areEqual(0.5, result.parts[0].alpha); + }, + + testHSLColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsl(100,50%, 75%)"); + + assert.isInstanceOf(parserlib.css.PropertyValue, result); + assert.areEqual(1, result.parts.length); + assert.areEqual("color", result.parts[0].type); + assert.areEqual(100, result.parts[0].hue); + assert.areEqual(0.5, result.parts[0].saturation); + assert.areEqual(0.75, result.parts[0].lightness); + }, + + testHSLAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsla(100,50%, 75%, 0.5)"); + + assert.isInstanceOf(parserlib.css.PropertyValue, result); + assert.areEqual(1, result.parts.length); + assert.areEqual("color", result.parts[0].type); + assert.areEqual(100, result.parts[0].hue); + assert.areEqual(0.5, result.parts[0].saturation); + assert.areEqual(0.75, result.parts[0].lightness); + assert.areEqual(0.5, result.parts[0].alpha); + }, + testColorValue: function(){ var parser = new Parser(); var result = parser.parsePropertyValue("red"); From 2eaa09d8d32860b20df014ec6a5daf902b86c937 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 31 Oct 2011 12:32:58 -0700 Subject: [PATCH 018/313] Fixed some validation --- build/node-parserlib.js | 75 +++++++++++++++++++++++++++--------- build/parserlib-core.js | 2 +- build/parserlib-css.js | 73 ++++++++++++++++++++++++++--------- build/parserlib.js | 75 +++++++++++++++++++++++++++--------- demos/css/CSSParserDemo.htm | 4 +- src/css/Properties.js | 71 ++++++++++++++++++++++++++-------- tests/css/CSSParserTests.htm | 47 ++++++++++++++++++++-- 7 files changed, 268 insertions(+), 79 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index f9301596..c3e99c1d 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3362,12 +3362,22 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ +//This file will likely change a lot! Very experimental! + var ValidationType = { "absolute-size": function(part){ return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); }, + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + "relative-size": function(part){ return this.identifier(part, "smaller | larger"); }, @@ -3415,6 +3425,10 @@ var ValidationType = { return this.uri(part); }, + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + "percentage": function(part){ return part.type == "percentage" || part == "0"; }, @@ -3462,12 +3476,12 @@ var Properties = { //B "backface-visibility": 1, "background": 1, - "background-attachment": [ "scroll | fixed | inherit" ], + "background-attachment": { multi: [ "attachment" ], separator: "," }, "background-break": 1, - "background-clip": 1, + "background-clip": { multi: [ "box" ], separator: "," }, "background-color": [ "color", "inherit" ], - "background-image": 1, - "background-origin": 1, + "background-image": { multi: [ "bg-image" ], separator: "," }, + "background-origin": { multi: [ "box" ], separator: "," }, "background-position": 1, "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, @@ -3735,6 +3749,7 @@ var Properties = { "text-indent": [ "length", "percentage", "inherit" ], "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, + "text-overflow": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": [ "normal | none | avoid" ], @@ -3818,8 +3833,10 @@ var Properties = { i, len, j, count, msg, values, + last, parts = value.parts; + //if there's a maximum set, use it (max can't be 0) if (spec.max) { if (parts.length > spec.max){ throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); @@ -3833,25 +3850,45 @@ var Properties = { for (i=0, len=parts.length; i < len; i++){ msg = []; valid = false; - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(values); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } + valid = true; + } + } else { + + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } } + if (!valid) { throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); } + + + last = parts[i]; } }; diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 9088a767..54254c2e 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 33df2753..e83a2794 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2458,12 +2458,22 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ +//This file will likely change a lot! Very experimental! + var ValidationType = { "absolute-size": function(part){ return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); }, + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + "relative-size": function(part){ return this.identifier(part, "smaller | larger"); }, @@ -2511,6 +2521,10 @@ var ValidationType = { return this.uri(part); }, + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + "percentage": function(part){ return part.type == "percentage" || part == "0"; }, @@ -2558,12 +2572,12 @@ var Properties = { //B "backface-visibility": 1, "background": 1, - "background-attachment": [ "scroll | fixed | inherit" ], + "background-attachment": { multi: [ "attachment" ], separator: "," }, "background-break": 1, - "background-clip": 1, + "background-clip": { multi: [ "box" ], separator: "," }, "background-color": [ "color", "inherit" ], - "background-image": 1, - "background-origin": 1, + "background-image": { multi: [ "bg-image" ], separator: "," }, + "background-origin": { multi: [ "box" ], separator: "," }, "background-position": 1, "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, @@ -2831,6 +2845,7 @@ var Properties = { "text-indent": [ "length", "percentage", "inherit" ], "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, + "text-overflow": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": [ "normal | none | avoid" ], @@ -2914,8 +2929,10 @@ var Properties = { i, len, j, count, msg, values, + last, parts = value.parts; + //if there's a maximum set, use it (max can't be 0) if (spec.max) { if (parts.length > spec.max){ throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); @@ -2929,25 +2946,45 @@ var Properties = { for (i=0, len=parts.length; i < len; i++){ msg = []; valid = false; - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(values); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } + valid = true; + } + } else { + + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } } + if (!valid) { throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); } + + + last = parts[i]; } }; diff --git a/build/parserlib.js b/build/parserlib.js index 8a3c197f..5aad0000 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 11:46:10 */ +/* Build time: 31-October-2011 12:28:42 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3362,12 +3362,22 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ +//This file will likely change a lot! Very experimental! + var ValidationType = { "absolute-size": function(part){ return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); }, + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + "relative-size": function(part){ return this.identifier(part, "smaller | larger"); }, @@ -3415,6 +3425,10 @@ var ValidationType = { return this.uri(part); }, + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + "percentage": function(part){ return part.type == "percentage" || part == "0"; }, @@ -3462,12 +3476,12 @@ var Properties = { //B "backface-visibility": 1, "background": 1, - "background-attachment": [ "scroll | fixed | inherit" ], + "background-attachment": { multi: [ "attachment" ], separator: "," }, "background-break": 1, - "background-clip": 1, + "background-clip": { multi: [ "box" ], separator: "," }, "background-color": [ "color", "inherit" ], - "background-image": 1, - "background-origin": 1, + "background-image": { multi: [ "bg-image" ], separator: "," }, + "background-origin": { multi: [ "box" ], separator: "," }, "background-position": 1, "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, @@ -3735,6 +3749,7 @@ var Properties = { "text-indent": [ "length", "percentage", "inherit" ], "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, + "text-overflow": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": [ "normal | none | avoid" ], @@ -3818,8 +3833,10 @@ var Properties = { i, len, j, count, msg, values, + last, parts = value.parts; + //if there's a maximum set, use it (max can't be 0) if (spec.max) { if (parts.length > spec.max){ throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); @@ -3833,25 +3850,45 @@ var Properties = { for (i=0, len=parts.length; i < len; i++){ msg = []; valid = false; - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(values); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } + valid = true; + } + } else { + + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } } + if (!valid) { throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); } + + + last = parts[i]; } }; diff --git a/demos/css/CSSParserDemo.htm b/demos/css/CSSParserDemo.htm index 948d7556..8ffa6839 100755 --- a/demos/css/CSSParserDemo.htm +++ b/demos/css/CSSParserDemo.htm @@ -183,8 +183,8 @@

CSS Parser Demo

parser.addListener("property", function(event){ log("Property '" + event.property + "' has a value of '" + event.value + "' and " + (event.important ? "is" : "isn't") + " important. (" + event.property.line + "," + event.property.col + ")"); - if (!event.valid){ - log(" Not valid: " + event.error.message); + if (event.invalid){ + log(" Not valid: " + event.invalid.message); } }); diff --git a/src/css/Properties.js b/src/css/Properties.js index 20dd7cbe..6e9c1114 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -1,9 +1,19 @@ +//This file will likely change a lot! Very experimental! + var ValidationType = { "absolute-size": function(part){ return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); }, + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + "relative-size": function(part){ return this.identifier(part, "smaller | larger"); }, @@ -51,6 +61,10 @@ var ValidationType = { return this.uri(part); }, + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + "percentage": function(part){ return part.type == "percentage" || part == "0"; }, @@ -98,12 +112,12 @@ var Properties = { //B "backface-visibility": 1, "background": 1, - "background-attachment": [ "scroll | fixed | inherit" ], + "background-attachment": { multi: [ "attachment" ], separator: "," }, "background-break": 1, - "background-clip": 1, + "background-clip": { multi: [ "box" ], separator: "," }, "background-color": [ "color", "inherit" ], - "background-image": 1, - "background-origin": 1, + "background-image": { multi: [ "bg-image" ], separator: "," }, + "background-origin": { multi: [ "box" ], separator: "," }, "background-position": 1, "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], "background-size": 1, @@ -371,6 +385,7 @@ var Properties = { "text-indent": [ "length", "percentage", "inherit" ], "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], "text-outline": 1, + "text-overflow": 1, "text-shadow": 1, "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], "text-wrap": [ "normal | none | avoid" ], @@ -454,8 +469,10 @@ var Properties = { i, len, j, count, msg, values, + last, parts = value.parts; + //if there's a maximum set, use it (max can't be 0) if (spec.max) { if (parts.length > spec.max){ throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); @@ -469,25 +486,45 @@ var Properties = { for (i=0, len=parts.length; i < len; i++){ msg = []; valid = false; - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(values); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } + valid = true; + } + } else { + + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } } + if (!valid) { throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); } + + + last = parts[i]; } }; diff --git a/tests/css/CSSParserTests.htm b/tests/css/CSSParserTests.htm index ba62a6b1..78a02d47 100644 --- a/tests/css/CSSParserTests.htm +++ b/tests/css/CSSParserTests.htm @@ -1535,7 +1535,7 @@

CSS Parser Tests

parser.addListener("property", function(event){ assert.isNull(event.invalid); }); - var result = parser.parse(".foo { background-attachment: inherit; }"); + var result = parser.parse(".foo { background-attachment: local; }"); }, @@ -1543,7 +1543,7 @@

CSS Parser Tests

var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ assert.isNotNull(event.invalid); - assert.areEqual("Expected one of (scroll | fixed | inherit) but found 'foo'.", event.invalid.message); + assert.areEqual("Expected attachment but found 'foo'.", event.invalid.message); }); var result = parser.parse(".foo { background-attachment: foo; }"); }, @@ -1683,7 +1683,48 @@

CSS Parser Tests

}); var result = parser.parse(".foo { opacity: 1}"); - } + }, + + testBackgroundImage1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: none}"); + }, + + testBackgroundImage2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png)}"); + }, + + testBackgroundImage3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), none}"); + }, + + testBackgroundImage4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), url(https://github.com/bar.png)}"); + }, + + testBackgroundImage5: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + assert.isNotNull(event.invalid); + assert.areEqual("Expected end of line but found ','.", event.invalid.message); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png),}"); + } From 66639fc40f02582878427201e381ef4e4d741f10 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 1 Nov 2011 11:39:22 -0700 Subject: [PATCH 019/313] Fixed validation problem --- build/node-parserlib.js | 6 +++--- build/parserlib-core.js | 2 +- build/parserlib-css.js | 4 ++-- build/parserlib.js | 6 +++--- src/css/Properties.js | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index c3e99c1d..68f4a338 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3639,7 +3639,7 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": [ "uri", "none | inherit" ], - "list-style-position": [ "inside | outsider | inherit" ], + "list-style-position": [ "inside | outside | inherit" ], "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 54254c2e..ca0cb893 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index e83a2794..4127a3e0 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2735,7 +2735,7 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": [ "uri", "none | inherit" ], - "list-style-position": [ "inside | outsider | inherit" ], + "list-style-position": [ "inside | outside | inherit" ], "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M diff --git a/build/parserlib.js b/build/parserlib.js index 5aad0000..9544563e 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 31-October-2011 12:28:42 */ +/* Build time: 1-November-2011 11:39:02 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3639,7 +3639,7 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": [ "uri", "none | inherit" ], - "list-style-position": [ "inside | outsider | inherit" ], + "list-style-position": [ "inside | outside | inherit" ], "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M diff --git a/src/css/Properties.js b/src/css/Properties.js index 6e9c1114..709bcc22 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -275,7 +275,7 @@ var Properties = { "line-stacking-strategy": 1, "list-style": 1, "list-style-image": [ "uri", "none | inherit" ], - "list-style-position": [ "inside | outsider | inherit" ], + "list-style-position": [ "inside | outside | inherit" ], "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], //M From 55b06012b454eb6f64fa4e91a248823b6732c895 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Tue, 1 Nov 2011 12:12:02 -0700 Subject: [PATCH 020/313] Added more validation --- build/node-parserlib.js | 10 +++++----- build/parserlib-core.js | 2 +- build/parserlib-css.js | 8 ++++---- build/parserlib.js | 10 +++++----- src/css/Properties.js | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 68f4a338..ba33d789 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3463,12 +3463,12 @@ var Properties = { "alignment-baseline": 1, "animation": 1, "animation-delay": 1, - "animation-direction": 1, + "animation-direction": { multi: [ "normal | alternate" ], separator: "," }, "animation-duration": 1, "animation-fill-mode": 1, - "animation-iteration-count": 1, + "animation-iteration-count": { multi: [ "number", "infinite"], separator: "," }, "animation-name": 1, - "animation-play-state": 1, + "animation-play-state": { multi: [ "running | paused" ], separator: "," }, "animation-timing-function": 1, "appearance": 1, "azimuth": 1, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index ca0cb893..e98fed39 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 4127a3e0..970a0b82 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2559,12 +2559,12 @@ var Properties = { "alignment-baseline": 1, "animation": 1, "animation-delay": 1, - "animation-direction": 1, + "animation-direction": { multi: [ "normal | alternate" ], separator: "," }, "animation-duration": 1, "animation-fill-mode": 1, - "animation-iteration-count": 1, + "animation-iteration-count": { multi: [ "number", "infinite"], separator: "," }, "animation-name": 1, - "animation-play-state": 1, + "animation-play-state": { multi: [ "running | paused" ], separator: "," }, "animation-timing-function": 1, "appearance": 1, "azimuth": 1, diff --git a/build/parserlib.js b/build/parserlib.js index 9544563e..99327d66 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 11:39:02 */ +/* Build time: 1-November-2011 12:11:55 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3463,12 +3463,12 @@ var Properties = { "alignment-baseline": 1, "animation": 1, "animation-delay": 1, - "animation-direction": 1, + "animation-direction": { multi: [ "normal | alternate" ], separator: "," }, "animation-duration": 1, "animation-fill-mode": 1, - "animation-iteration-count": 1, + "animation-iteration-count": { multi: [ "number", "infinite"], separator: "," }, "animation-name": 1, - "animation-play-state": 1, + "animation-play-state": { multi: [ "running | paused" ], separator: "," }, "animation-timing-function": 1, "appearance": 1, "azimuth": 1, diff --git a/src/css/Properties.js b/src/css/Properties.js index 709bcc22..be0e2571 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -99,12 +99,12 @@ var Properties = { "alignment-baseline": 1, "animation": 1, "animation-delay": 1, - "animation-direction": 1, + "animation-direction": { multi: [ "normal | alternate" ], separator: "," }, "animation-duration": 1, "animation-fill-mode": 1, - "animation-iteration-count": 1, + "animation-iteration-count": { multi: [ "number", "infinite"], separator: "," }, "animation-name": 1, - "animation-play-state": 1, + "animation-play-state": { multi: [ "running | paused" ], separator: "," }, "animation-timing-function": 1, "appearance": 1, "azimuth": 1, From e110129f303cd02e4577a58bc15603eea4b98d99 Mon Sep 17 00:00:00 2001 From: David Flanagan Date: Tue, 15 Nov 2011 14:05:18 -0800 Subject: [PATCH 021/313] add parseStyleAttribute() function --- src/css/Parser.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/css/Parser.js b/src/css/Parser.js index d0d47cd3..f05cd1c1 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -2156,8 +2156,20 @@ Parser.prototype = function(){ //otherwise return result return result; + }, + + /** + * Parses an HTML style attribute: a set of CSS declarations + * separated by semicolons. + * @param {String} input The text to parse as a style attribute + * @return {void} + * @method parseStyleAttribute + */ + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); } - }; //copy over onto prototype From e17fd7e5f689a03bfb106e89f321545a31e83d7c Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 16 Nov 2011 13:12:36 -0800 Subject: [PATCH 022/313] Added error recovery for unknown @ rules --- build/node-parserlib.js | 47 +++++++++++++++++++++++++++++++----- build/parserlib-core.js | 2 +- build/parserlib-css.js | 45 ++++++++++++++++++++++++++++++---- build/parserlib.js | 47 +++++++++++++++++++++++++++++++----- src/css/Parser.js | 32 +++++++++++++++++++++++- src/css/TokenStream.js | 10 +++++--- src/css/Tokens.js | 1 + tests/css/CSSTokensTests.htm | 6 ++++- 8 files changed, 167 insertions(+), 23 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index ba33d789..fb33c259 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1258,6 +1258,7 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, charset = null, + count, token, tt; @@ -1304,7 +1305,36 @@ Parser.prototype = function(){ case Tokens.KEYFRAMES_SYM: this._keyframes(); this._skipCruft(); - break; + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + + //skip braces + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + //not a syntax error, rethrow it + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + } + break; case Tokens.S: this._readWhitespace(); break; @@ -4728,9 +4758,13 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //if it's not valid, use the first character only and reset the reader if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){ - tt = Tokens.CHAR; - rule = first; - reader.reset(); + if (rule.length > 1){ + tt = Tokens.UNKNOWN_SYM; + } else { + tt = Tokens.CHAR; + rule = first; + reader.reset(); + } } return this.createToken(tt, rule, startLine, startCol); @@ -5396,6 +5430,7 @@ var Tokens = [ { name: "FONT_FACE_SYM", text: "@font-face"}, { name: "CHARSET_SYM", text: "@charset"}, { name: "NAMESPACE_SYM", text: "@namespace"}, + { name: "UNKNOWN_SYM" }, //{ name: "ATKEYWORD"}, //CSS3 animations diff --git a/build/parserlib-core.js b/build/parserlib-core.js index e98fed39..136fd342 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 970a0b82..3792c821 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -354,6 +354,7 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, charset = null, + count, token, tt; @@ -400,7 +401,36 @@ Parser.prototype = function(){ case Tokens.KEYFRAMES_SYM: this._keyframes(); this._skipCruft(); - break; + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + + //skip braces + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + //not a syntax error, rethrow it + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + } + break; case Tokens.S: this._readWhitespace(); break; @@ -3824,9 +3854,13 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //if it's not valid, use the first character only and reset the reader if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){ - tt = Tokens.CHAR; - rule = first; - reader.reset(); + if (rule.length > 1){ + tt = Tokens.UNKNOWN_SYM; + } else { + tt = Tokens.CHAR; + rule = first; + reader.reset(); + } } return this.createToken(tt, rule, startLine, startCol); @@ -4492,6 +4526,7 @@ var Tokens = [ { name: "FONT_FACE_SYM", text: "@font-face"}, { name: "CHARSET_SYM", text: "@charset"}, { name: "NAMESPACE_SYM", text: "@namespace"}, + { name: "UNKNOWN_SYM" }, //{ name: "ATKEYWORD"}, //CSS3 animations diff --git a/build/parserlib.js b/build/parserlib.js index 99327d66..4eaf4b6a 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ var parserlib = {}; (function(){ @@ -925,7 +925,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 1-November-2011 12:11:55 */ +/* Build time: 16-November-2011 01:11:51 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1258,6 +1258,7 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, charset = null, + count, token, tt; @@ -1304,7 +1305,36 @@ Parser.prototype = function(){ case Tokens.KEYFRAMES_SYM: this._keyframes(); this._skipCruft(); - break; + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + + //skip braces + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + //not a syntax error, rethrow it + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + } + break; case Tokens.S: this._readWhitespace(); break; @@ -4728,9 +4758,13 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //if it's not valid, use the first character only and reset the reader if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){ - tt = Tokens.CHAR; - rule = first; - reader.reset(); + if (rule.length > 1){ + tt = Tokens.UNKNOWN_SYM; + } else { + tt = Tokens.CHAR; + rule = first; + reader.reset(); + } } return this.createToken(tt, rule, startLine, startCol); @@ -5396,6 +5430,7 @@ var Tokens = [ { name: "FONT_FACE_SYM", text: "@font-face"}, { name: "CHARSET_SYM", text: "@charset"}, { name: "NAMESPACE_SYM", text: "@namespace"}, + { name: "UNKNOWN_SYM" }, //{ name: "ATKEYWORD"}, //CSS3 animations diff --git a/src/css/Parser.js b/src/css/Parser.js index d0d47cd3..8aedd91d 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -71,6 +71,7 @@ Parser.prototype = function(){ var tokenStream = this._tokenStream, charset = null, + count, token, tt; @@ -117,7 +118,36 @@ Parser.prototype = function(){ case Tokens.KEYFRAMES_SYM: this._keyframes(); this._skipCruft(); - break; + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + + //skip braces + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + //not a syntax error, rethrow it + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + } + break; case Tokens.S: this._readWhitespace(); break; diff --git a/src/css/TokenStream.js b/src/css/TokenStream.js index 300152b3..e233c439 100755 --- a/src/css/TokenStream.js +++ b/src/css/TokenStream.js @@ -362,9 +362,13 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //if it's not valid, use the first character only and reset the reader if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){ - tt = Tokens.CHAR; - rule = first; - reader.reset(); + if (rule.length > 1){ + tt = Tokens.UNKNOWN_SYM; + } else { + tt = Tokens.CHAR; + rule = first; + reader.reset(); + } } return this.createToken(tt, rule, startLine, startCol); diff --git a/src/css/Tokens.js b/src/css/Tokens.js index cdf26352..ed364a3a 100644 --- a/src/css/Tokens.js +++ b/src/css/Tokens.js @@ -31,6 +31,7 @@ var Tokens = [ { name: "FONT_FACE_SYM", text: "@font-face"}, { name: "CHARSET_SYM", text: "@charset"}, { name: "NAMESPACE_SYM", text: "@namespace"}, + { name: "UNKNOWN_SYM" }, //{ name: "ATKEYWORD"}, //CSS3 animations diff --git a/tests/css/CSSTokensTests.htm b/tests/css/CSSTokensTests.htm index c46af4b6..55f1d7f5 100755 --- a/tests/css/CSSTokensTests.htm +++ b/tests/css/CSSTokensTests.htm @@ -186,7 +186,11 @@

CSS Tokens Tests

//animation "@-webkit-keyframes": CSSTokens.KEYFRAMES_SYM, "@-moz-keyframes" : CSSTokens.KEYFRAMES_SYM, - "@keyframes" : CSSTokens.KEYFRAMES_SYM + "@keyframes" : CSSTokens.KEYFRAMES_SYM, + + //errors + "@foo" : CSSTokens.UNKNOWN_SYM, + "@bar" : CSSTokens.UNKNOWN_SYM }; var patterns; From 427f6dec18a7c8443c0dd0f0c23b438976b042a5 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 16 Nov 2011 13:13:57 -0800 Subject: [PATCH 023/313] Updated docs --- docs/css.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/css.md b/docs/css.md index 814cf376..b61c757a 100644 --- a/docs/css.md +++ b/docs/css.md @@ -304,4 +304,6 @@ The CSS parser's goal is to be on-par with error recovery of CSS parsers in brow text-decoration: underline; } -* **@ Rules** - there are certain @ rules that are only valid in certain contexts. The parser will skip over `@charset`, `@namespace`, and `@import` if they're found anywhere other than the beginning of the input. \ No newline at end of file +* **@ Rules** - there are certain @ rules that are only valid in certain contexts. The parser will skip over `@charset`, `@namespace`, and `@import` if they're found anywhere other than the beginning of the input. + +* **Unknown @ Rules** - any @ rules that isn't recognized is automatically skipped, meaning the entire block after it is not parsed. \ No newline at end of file From a607d1e6a565d3b0964b6415917bb11a9e5bb58f Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 17 Nov 2011 10:13:52 -0800 Subject: [PATCH 024/313] Added JSHint linting, new build system --- CHANGELOG | 0 build.xml | 94 +- build/node-parserlib.js | 69 +- build/parserlib-core.js | 7 +- build/parserlib-css.js | 62 +- build/parserlib.js | 69 +- lib/js.jar | Bin 0 -> 1122370 bytes lib/jshint.js | 3963 ++++++++++++++++++++++++++++++++++ lib/yuitest-rhino-cli.js | 3955 +++++++++++++++++++++++++++++++++ src/css/Combinator.js | 1 + src/css/MediaFeature.js | 1 + src/css/MediaQuery.js | 1 + src/css/Parser.js | 15 +- src/css/Properties.js | 1 + src/css/PropertyName.js | 1 + src/css/PropertyValue.js | 1 + src/css/PropertyValuePart.js | 3 +- src/css/Selector.js | 1 + src/css/SelectorPart.js | 1 + src/css/SelectorSubPart.js | 1 + src/css/Specificity.js | 2 + src/css/TokenStream.js | 31 +- src/util/TokenStreamBase.js | 5 +- 23 files changed, 8174 insertions(+), 110 deletions(-) create mode 100644 CHANGELOG create mode 100644 lib/js.jar create mode 100644 lib/jshint.js create mode 100644 lib/yuitest-rhino-cli.js diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..e69de29b diff --git a/build.xml b/build.xml index a7125b72..1b7eb59b 100644 --- a/build.xml +++ b/build.xml @@ -1,17 +1,27 @@ - + + + + + + + + + + + @@ -20,6 +30,64 @@ locale="en,US"/> + + + + + + + + + + + + + + + + + +
${SIMPLE_DATE} - v${csslint.version} + + ${git.changelog} + +
+ +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + @@ -34,7 +102,7 @@
/*! ${license.text} */ - /* Build time: ${RIGHT_NOW} */ + /* Version v@VERSION@, Build time: ${RIGHT_NOW} */ var parserlib = {}; (function(){
@@ -60,7 +128,7 @@
/* ${license.text} */ - /* Build time: ${RIGHT_NOW} */ + /* Version v@VERSION@, Build time: ${RIGHT_NOW} */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -139,9 +207,27 @@ + + + + + + + + + + + + + + + + + + - + diff --git a/build/node-parserlib.js b/build/node-parserlib.js index fb33c259..21150dd4 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ var parserlib = {}; (function(){ @@ -493,6 +493,8 @@ SyntaxUnit.prototype = { } }; +/*global StringReader, SyntaxError*/ + /** * Generic TokenStream providing base functionality. * @class TokenStreamBase @@ -509,7 +511,6 @@ function TokenStreamBase(input, tokenData){ * @property _reader * @private */ - //this._reader = (typeof input == "string") ? new StringReader(input) : input; this._reader = input ? new StringReader(input.toString()) : null; /** @@ -675,7 +676,7 @@ TokenStreamBase.prototype = { */ advance: function(tokenTypes, channel){ - while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){ + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } @@ -925,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1075,6 +1076,7 @@ var Colors = { yellow :"#ffff00", yellowgreen :"#9acd32" }; +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -1112,6 +1114,7 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; +/*global SyntaxUnit, Parser*/ /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -1143,6 +1146,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; +/*global SyntaxUnit, Parser*/ /** * Represents an individual media query. * @namespace parserlib.css @@ -1185,6 +1189,10 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; +/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, + PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, + PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ + /** * A CSS3 parser. * @namespace parserlib.css @@ -1332,7 +1340,7 @@ Parser.prototype = function(){ } else { //not a syntax error, rethrow it - throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); } break; case Tokens.S: @@ -3195,10 +3203,9 @@ Parser.prototype = function(){ tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ //if there's a semicolon, then there might be another declaration - this._readDeclarations(false, readMargins); - } else if (tt == Tokens.RBRACE){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ //if there's a right brace, the rule is finished so don't do anything - } else { //otherwise, rethrow the error because it wasn't handled properly throw ex; } @@ -3379,7 +3386,9 @@ Parser.prototype = function(){ //copy over onto prototype for (prop in additions){ - proto[prop] = additions[prop]; + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } } return proto; @@ -3393,6 +3402,7 @@ nth ; */ //This file will likely change a lot! Very experimental! +/*global ValidationError*/ var ValidationType = { @@ -3927,6 +3937,7 @@ var Properties = { } } })(); +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -3956,6 +3967,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3984,6 +3996,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; +/*global SyntaxUnit, Parser, Colors*/ /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4137,7 +4150,7 @@ function PropertyValuePart(text, line, col){ } PropertyValuePart.prototype = new SyntaxUnit(); -PropertyValuePart.prototype.constructor = PropertyValue; +PropertyValuePart.prototype.constructor = PropertyValuePart; /** * Create a new syntax unit based solely on the given token. @@ -4164,6 +4177,7 @@ Pseudos.CLASS = 2; Pseudos.isElement = function(pseudo){ return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; }; +/*global SyntaxUnit, Parser, Specificity*/ /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -4198,6 +4212,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4239,6 +4254,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; +/*global SyntaxUnit, Parser*/ /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4274,6 +4290,7 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/*global Pseudos, SelectorPart*/ /** * Represents a selector's specificity. * @namespace parserlib.css @@ -4345,6 +4362,7 @@ Specificity.prototype = { Specificity.calculate = function(selector){ var i, len, + part, b=0, c=0, d=0; function updateValues(part){ @@ -4394,7 +4412,7 @@ Specificity.calculate = function(selector){ return new Specificity(0, b, c, d); }; - +/*global Tokens, TokenStreamBase*/ var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, @@ -4406,31 +4424,31 @@ var h = /^[0-9a-fA-F]$/, function isHexDigit(c){ - return c != null && h.test(c); + return c !== null && h.test(c); } function isDigit(c){ - return c != null && /\d/.test(c); + return c !== null && /\d/.test(c); } function isWhitespace(c){ - return c != null && /\s/.test(c); + return c !== null && /\s/.test(c); } function isNewLine(c){ - return c != null && nl.test(c); + return c !== null && nl.test(c); } function isNameStart(c){ - return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); + return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); } function isNameChar(c){ - return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c)); + return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c)); } function isIdentStart(c){ - return c != null && (isNameStart(c) || /\-\\/.test(c)); + return c !== null && (isNameStart(c) || /\-\\/.test(c)); } function mix(receiver, supplier){ @@ -4621,8 +4639,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { token = this.unicodeRangeToken(c, startLine, startCol); break; } - /*falls through*/ - + /* falls through */ default: /* @@ -4675,11 +4692,9 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //make sure this token is wanted //TODO: check channel break; - - c = reader.read(); } - if (!token && c == null){ + if (!token && c === null){ token = this.createToken(Tokens.EOF,null,startLine,startCol); } @@ -4963,7 +4978,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { break; } else { temp = this.readComment(c); - if (temp == ""){ //broken! + if (temp === ""){ //broken! break; } } @@ -5104,7 +5119,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ tt = Tokens.INVALID; } @@ -5269,7 +5284,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ string = ""; } @@ -5305,7 +5320,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if there was no inner value or the next character isn't closing paren, it's not a URI - if (inner == "" || c != ")"){ + if (inner === "" || c != ")"){ uri = first; reader.reset(); } else { diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 136fd342..58f9527f 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ var parserlib = {}; (function(){ @@ -493,6 +493,8 @@ SyntaxUnit.prototype = { } }; +/*global StringReader, SyntaxError*/ + /** * Generic TokenStream providing base functionality. * @class TokenStreamBase @@ -509,7 +511,6 @@ function TokenStreamBase(input, tokenData){ * @property _reader * @private */ - //this._reader = (typeof input == "string") ? new StringReader(input) : input; this._reader = input ? new StringReader(input.toString()) : null; /** @@ -675,7 +676,7 @@ TokenStreamBase.prototype = { */ advance: function(tokenTypes, channel){ - while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){ + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 3792c821..bfbd8e45 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -171,6 +171,7 @@ var Colors = { yellow :"#ffff00", yellowgreen :"#9acd32" }; +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -208,6 +209,7 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; +/*global SyntaxUnit, Parser*/ /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -239,6 +241,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; +/*global SyntaxUnit, Parser*/ /** * Represents an individual media query. * @namespace parserlib.css @@ -281,6 +284,10 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; +/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, + PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, + PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ + /** * A CSS3 parser. * @namespace parserlib.css @@ -428,7 +435,7 @@ Parser.prototype = function(){ } else { //not a syntax error, rethrow it - throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); } break; case Tokens.S: @@ -2291,10 +2298,9 @@ Parser.prototype = function(){ tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ //if there's a semicolon, then there might be another declaration - this._readDeclarations(false, readMargins); - } else if (tt == Tokens.RBRACE){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ //if there's a right brace, the rule is finished so don't do anything - } else { //otherwise, rethrow the error because it wasn't handled properly throw ex; } @@ -2475,7 +2481,9 @@ Parser.prototype = function(){ //copy over onto prototype for (prop in additions){ - proto[prop] = additions[prop]; + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } } return proto; @@ -2489,6 +2497,7 @@ nth ; */ //This file will likely change a lot! Very experimental! +/*global ValidationError*/ var ValidationType = { @@ -3023,6 +3032,7 @@ var Properties = { } } })(); +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -3052,6 +3062,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3080,6 +3091,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; +/*global SyntaxUnit, Parser, Colors*/ /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -3233,7 +3245,7 @@ function PropertyValuePart(text, line, col){ } PropertyValuePart.prototype = new SyntaxUnit(); -PropertyValuePart.prototype.constructor = PropertyValue; +PropertyValuePart.prototype.constructor = PropertyValuePart; /** * Create a new syntax unit based solely on the given token. @@ -3260,6 +3272,7 @@ Pseudos.CLASS = 2; Pseudos.isElement = function(pseudo){ return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; }; +/*global SyntaxUnit, Parser, Specificity*/ /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -3294,6 +3307,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -3335,6 +3349,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; +/*global SyntaxUnit, Parser*/ /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -3370,6 +3385,7 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/*global Pseudos, SelectorPart*/ /** * Represents a selector's specificity. * @namespace parserlib.css @@ -3441,6 +3457,7 @@ Specificity.prototype = { Specificity.calculate = function(selector){ var i, len, + part, b=0, c=0, d=0; function updateValues(part){ @@ -3490,7 +3507,7 @@ Specificity.calculate = function(selector){ return new Specificity(0, b, c, d); }; - +/*global Tokens, TokenStreamBase*/ var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, @@ -3502,31 +3519,31 @@ var h = /^[0-9a-fA-F]$/, function isHexDigit(c){ - return c != null && h.test(c); + return c !== null && h.test(c); } function isDigit(c){ - return c != null && /\d/.test(c); + return c !== null && /\d/.test(c); } function isWhitespace(c){ - return c != null && /\s/.test(c); + return c !== null && /\s/.test(c); } function isNewLine(c){ - return c != null && nl.test(c); + return c !== null && nl.test(c); } function isNameStart(c){ - return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); + return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); } function isNameChar(c){ - return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c)); + return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c)); } function isIdentStart(c){ - return c != null && (isNameStart(c) || /\-\\/.test(c)); + return c !== null && (isNameStart(c) || /\-\\/.test(c)); } function mix(receiver, supplier){ @@ -3717,8 +3734,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { token = this.unicodeRangeToken(c, startLine, startCol); break; } - /*falls through*/ - + /* falls through */ default: /* @@ -3771,11 +3787,9 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //make sure this token is wanted //TODO: check channel break; - - c = reader.read(); } - if (!token && c == null){ + if (!token && c === null){ token = this.createToken(Tokens.EOF,null,startLine,startCol); } @@ -4059,7 +4073,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { break; } else { temp = this.readComment(c); - if (temp == ""){ //broken! + if (temp === ""){ //broken! break; } } @@ -4200,7 +4214,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ tt = Tokens.INVALID; } @@ -4365,7 +4379,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ string = ""; } @@ -4401,7 +4415,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if there was no inner value or the next character isn't closing paren, it's not a URI - if (inner == "" || c != ")"){ + if (inner === "" || c != ")"){ uri = first; reader.reset(); } else { diff --git a/build/parserlib.js b/build/parserlib.js index 4eaf4b6a..83917e60 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ var parserlib = {}; (function(){ @@ -493,6 +493,8 @@ SyntaxUnit.prototype = { } }; +/*global StringReader, SyntaxError*/ + /** * Generic TokenStream providing base functionality. * @class TokenStreamBase @@ -509,7 +511,6 @@ function TokenStreamBase(input, tokenData){ * @property _reader * @private */ - //this._reader = (typeof input == "string") ? new StringReader(input) : input; this._reader = input ? new StringReader(input.toString()) : null; /** @@ -675,7 +676,7 @@ TokenStreamBase.prototype = { */ advance: function(tokenTypes, channel){ - while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){ + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } @@ -925,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build time: 16-November-2011 01:11:51 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1075,6 +1076,7 @@ var Colors = { yellow :"#ffff00", yellowgreen :"#9acd32" }; +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -1112,6 +1114,7 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; +/*global SyntaxUnit, Parser*/ /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css @@ -1143,6 +1146,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; +/*global SyntaxUnit, Parser*/ /** * Represents an individual media query. * @namespace parserlib.css @@ -1185,6 +1189,10 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; +/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, + PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, + PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ + /** * A CSS3 parser. * @namespace parserlib.css @@ -1332,7 +1340,7 @@ Parser.prototype = function(){ } else { //not a syntax error, rethrow it - throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); } break; case Tokens.S: @@ -3195,10 +3203,9 @@ Parser.prototype = function(){ tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ //if there's a semicolon, then there might be another declaration - this._readDeclarations(false, readMargins); - } else if (tt == Tokens.RBRACE){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ //if there's a right brace, the rule is finished so don't do anything - } else { //otherwise, rethrow the error because it wasn't handled properly throw ex; } @@ -3379,7 +3386,9 @@ Parser.prototype = function(){ //copy over onto prototype for (prop in additions){ - proto[prop] = additions[prop]; + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } } return proto; @@ -3393,6 +3402,7 @@ nth ; */ //This file will likely change a lot! Very experimental! +/*global ValidationError*/ var ValidationType = { @@ -3927,6 +3937,7 @@ var Properties = { } } })(); +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css @@ -3956,6 +3967,7 @@ PropertyName.prototype.constructor = PropertyName; PropertyName.prototype.toString = function(){ return (this.hack ? this.hack : "") + this.text; }; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values @@ -3984,6 +3996,7 @@ function PropertyValue(parts, line, col){ PropertyValue.prototype = new SyntaxUnit(); PropertyValue.prototype.constructor = PropertyValue; +/*global SyntaxUnit, Parser, Colors*/ /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -4137,7 +4150,7 @@ function PropertyValuePart(text, line, col){ } PropertyValuePart.prototype = new SyntaxUnit(); -PropertyValuePart.prototype.constructor = PropertyValue; +PropertyValuePart.prototype.constructor = PropertyValuePart; /** * Create a new syntax unit based solely on the given token. @@ -4164,6 +4177,7 @@ Pseudos.CLASS = 2; Pseudos.isElement = function(pseudo){ return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; }; +/*global SyntaxUnit, Parser, Specificity*/ /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). @@ -4198,6 +4212,7 @@ function Selector(parts, line, col){ Selector.prototype = new SyntaxUnit(); Selector.prototype.constructor = Selector; +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as @@ -4239,6 +4254,7 @@ function SelectorPart(elementName, modifiers, text, line, col){ SelectorPart.prototype = new SyntaxUnit(); SelectorPart.prototype.constructor = SelectorPart; +/*global SyntaxUnit, Parser*/ /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. @@ -4274,6 +4290,7 @@ function SelectorSubPart(text, type, line, col){ SelectorSubPart.prototype = new SyntaxUnit(); SelectorSubPart.prototype.constructor = SelectorSubPart; +/*global Pseudos, SelectorPart*/ /** * Represents a selector's specificity. * @namespace parserlib.css @@ -4345,6 +4362,7 @@ Specificity.prototype = { Specificity.calculate = function(selector){ var i, len, + part, b=0, c=0, d=0; function updateValues(part){ @@ -4394,7 +4412,7 @@ Specificity.calculate = function(selector){ return new Specificity(0, b, c, d); }; - +/*global Tokens, TokenStreamBase*/ var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, @@ -4406,31 +4424,31 @@ var h = /^[0-9a-fA-F]$/, function isHexDigit(c){ - return c != null && h.test(c); + return c !== null && h.test(c); } function isDigit(c){ - return c != null && /\d/.test(c); + return c !== null && /\d/.test(c); } function isWhitespace(c){ - return c != null && /\s/.test(c); + return c !== null && /\s/.test(c); } function isNewLine(c){ - return c != null && nl.test(c); + return c !== null && nl.test(c); } function isNameStart(c){ - return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); + return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); } function isNameChar(c){ - return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c)); + return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c)); } function isIdentStart(c){ - return c != null && (isNameStart(c) || /\-\\/.test(c)); + return c !== null && (isNameStart(c) || /\-\\/.test(c)); } function mix(receiver, supplier){ @@ -4621,8 +4639,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { token = this.unicodeRangeToken(c, startLine, startCol); break; } - /*falls through*/ - + /* falls through */ default: /* @@ -4675,11 +4692,9 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //make sure this token is wanted //TODO: check channel break; - - c = reader.read(); } - if (!token && c == null){ + if (!token && c === null){ token = this.createToken(Tokens.EOF,null,startLine,startCol); } @@ -4963,7 +4978,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { break; } else { temp = this.readComment(c); - if (temp == ""){ //broken! + if (temp === ""){ //broken! break; } } @@ -5104,7 +5119,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ tt = Tokens.INVALID; } @@ -5269,7 +5284,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ string = ""; } @@ -5305,7 +5320,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if there was no inner value or the next character isn't closing paren, it's not a URI - if (inner == "" || c != ")"){ + if (inner === "" || c != ")"){ uri = first; reader.reset(); } else { diff --git a/lib/js.jar b/lib/js.jar new file mode 100644 index 0000000000000000000000000000000000000000..878b0d9422bcb0235f2e288dc92fb5012506a59d GIT binary patch literal 1122370 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

%PH4;dV~IucYm^X-N3gC}(ts}MuI%4c94$7_ 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�gHgdJ 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∈SVXYm}u~85d^ttcj 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

7PbSjp${{4`tce+CK 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

psOf+O&p8I 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 z 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�z@AilR) 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 o=!9_^si{M7dO* ziPi3hBz^=beWVeN&O7GEWYX{zwRv}nkGTi2%CYSPqKI}9*c(1`qsb5Ii->OLL&Yst zY{&8y_#G$wj-ZAGTl5#Kjv7{#I^5qioMGjx`<&w6<56dMDtuB^ttgcRL=2q5O+#X}GU)wp4 z-COPgI^&uvKt9VwyW=Nv{sE8nE~RFl(KzaGi01{`i+Qp;%K0;fxB6e-Sp+9iK##1B z@Lr#giV3UL1_p`|2h!_ zs2~vyScWaw%w9XXFXLfF7_Y!4(tj#~EU=lw)jzErmJ|2`o1(|hMXV!r=#fuwC}UF0 zbay#&`JHtBZVS7rrwMgs{8Ui5yPrn26Wy(v=Hysfk?}ZeDDkgN>|t!&x;<^>6+==o z;Ui3WnyhD;`68{;ByW&{g6=h@ca(qV(q5IZnGV8ernt}{YwDbMF_45GM zkcM+}UpBOMVa|6n*FDzQwsup051ug%En|KUimzy!qUMewkqecVRbeQ7c)LB`%J45C zKl^|U${3;30HG)GYTm?|r2S8{_D&o-F4H(Y<|oZk$Kg09tSvYNXXGuUw>_jzA~obe zgHD#qi19y;xhPKqZjCU8LpE-Zk3%`y7Y1v{L_@tGnk^V3V}KKL`zM&*KgiDzp*>Vi zLZoII5Van7LQ|V_ltVDpnw4{=9f=fo7YRVt*ibFa=Z5_Q-G| z5{?+3#djbIrpEW!d>{oghz783>7G?TV2x}j{p-pGI&_(y74hJ9?bQAVZP-7n=phK% zSb$pEzXvP`h8VRu?Q#9JdN%MHB=Y_KUiK7T^2*Fl5N9S|Fx4rT1NW09#TRGko_Og& z*Yeaavr1@0|22hPF))1e;+m!714<4UX!`fwNXO3%yCv3zej#&;UlQ!XnBIgSE{%Rt zdzKf6qqe0f%Y&u8$^1Yw-S*PbW=v#d**n~WYsX9=&Pc~7WsVp-`L>4n@?GpR#llpY zH(FsKXWd-?o{a|GLWfo!qug9geXS-Z)`Dzw(BgfxoRori@HtLFEy<(!1}!H(6RGK1mcWp48I1L=^ zz_%T}O1+Z#e4Vv)(KyZpLoZ%ktCFLgl}L5FaIQ18PPm#c*HV8XCg~i^s)Ru{aR|pY zck*5OAp{VsP>Wu*(>SU0Ii!cg2kj zYL2t=2X-t!_i*|#I&9zVapD!sfBa!5JZ4{Ma#>ngF+c{`)Jf?X4KT)f&XySL23XaM zQFW|8NL=o79`==Z%#&@}`^)6SP3v(fIZTv#M!Y`N_2Cf7A z&&_4nw#q6k*BG)@>pGcB7xIR-$FZi%fB$n<`nM3N`sK8Sa-F6P-!XSUSFW2fWK2GE zq(DlxtcxEJ;Mst!C+5c^VyO({hg+18xu>uVGrO{X69?q+xcCx0k~r{@SDMnUXSC<} zbeB)pZ<6Sh+L0P4Eyh8gTDHh7J`R7lGsyhHyq9#&t7#c4AyTd;m}(kxyEg1h;POdf zKO|$tO%U9J4Zgj%PogrkoN!!PXOE#DRqZW7Bj^?jUeieGrIekGq1y-Tu=HBA@)R`B5nD zC*#_@D7bt}ch)?t9FJM9A~K$iY1=5(pHRiYQ4YkdbcKmru!wiq?;KEThi|o9 zH5J*;sV&iUNb;qyc>r?g>>?{&hg*$d$0f3^ls)rTJdUWA_`s;k}aUnRRSf5c$hPcKeO+ z$f@ZPoC9)+bHM+}`ls`O1y;Eg(vMfHz_8?V3a^Br5Ezi3UOS-mBEdm?in#f=#VAzI`#Xg z?z><0kb17#wwLJm!8tV^`PqS4&uxRx6jrIgy7{y@9xycqMouO&FQ0Y;MsQ70im(a! z?_G-m8*ii2Ft3r>hsoQbxPO?_R^fBOc>CM0$ncx>Scme1gFzTC9MA2*-H*?)(44Y= zeXw7@XJGJDm0)~OkjU8hXJ(C$*u+lB8h z=cj%16te(%@=i$fN7Bd&WexsPj=FA#CaJ(+5f+C|edgglB^^=<70;xw{6aD%onZET z>mjmD^OnNOPxeH<5M3h7jmosSBdeDao+rCg#Tzm0axJz}f+YbVc9QsnKMYctJVQkJ{mj(GOl zBF3VsMx$PI)#V$iUH;3WHZ4~l-b<_YombN_jJtG4m=-szR6G>MPrx5-Rct@Y)@OK6 z74NR5YDIYqE&1@VL`h;rvHHguVoIEpSBJFWqPa&jPE`M-tYfpPnXA7vviqrqf~IQg zghkx|2DNPw$;7`a-&hQM4bL0joedbL4%Xy0+|5(XiW^#dS%(-nvY_aE(?V?U`HiCN z_n;wGPB@5G`6#oLBC_cac79PWvvpvkLO7T`ZthI^Fn2lx+FBKJ_-v4x4kLP_sP;@u zVc2ZAY&&fAx~Vo`{3_0#CU-P_kjI|K-cqnL3}YBm6I_c~=yyvRiX~WQQeBANx@~8u z#^81>Znh4}m4%0Mki&r4o1}NLLkQOT83?+3*UV~Y{F44TI}dTU+3gRNenf!D$>24% zz(MkWdu-^zdN@6**ap(2X?iS}B~yF&gNYu?VNY_L#U?1z7m<*^VHo1@!JB+58m1fX zCdw0yklWGh)BM*O#-(Si3rzY>bk(n`T>ybG2G1xj^MpHg&&(&&c@Ws8j$nwuxRS~IUGyb|U}*2)Neh<`g$h#CC#FZB3z;R^rUD{ERC@4XrzL!NC*6)IC?79M*N~%yq#RYuF2YO`}V)@82!Ez zDGo-){QM&};^bcmDJXyL-|2pbx;VUKfhB0@d4Oh4luz<@6YYv!KrVG7&l9Yap5l`} zbG&}5K2tF2cBmgvtv_HjG0JcB`b^)IJfDuyBfJ6^ zs<83zwY*i(1s76~+qbfva}W<9E)p?i*O>g4 zKvF88WFc$U^nR}cxA%qdfIOgrC3V*#cJEi**JPb6^qPhBCE!3kph0Egn(g=&VhsEv zu_=>?{rz2~Bw5I^_D=#H$wz5ZypUDyWC0iB9uv0S3t+76oq}w}h!gjPZj3QtWNp@n z>+yywF7ich%;cl}hCOiAJ3i33XH1BF=a2~R8Z;lL^nx|k@h*3u^^tZ1^Et*n)z78y z5sEV($i8`FG&}ds#TNc);)yZCFXQYMlz2>Rl07V*%Og3Gqch~7hz4hwZ*7GcCGM64 z%9N9UaVtBuu1A%zly+xT!ZMhdC0*`OF3r*t*K+%HYI%jSJ)0we+#++&evR2X^RKw$ zCFs;lkn%MVfbNfp?gvbI8Gjk)OdS*gMh})^{IQ7)u$(nEzKSW7!&bW@rt}5eFOB zFZ>G`PBhU@#gS0T2$M~^b&b8D2V;tQMsRW=ynIV7GXaIx$Y^`Mm8DVP)7f(!KIT#^ z#pbs}kIr(#lFB#Y1cRDNM-WfF!dk;6%rzZcY5I2pb*DxB?;f3uMUW_*1+M1xoPkz| z(r~=|d@y#i8rAg&*x|O?IfL`u8+dC-C#8a`U1X;zrVLxrQnfRwc}cqk3`C1?G%FE# zh-XrfUZgOF(4xfP`chi~}O`TRqQYR8KT zQAftG!B`2v_D{{!rGjMQzvU?h;gKvH+Y-z#6V9!(Z1M7J1#QpZ{>?$!fkAk!3X2=h zd#;B&=TDav+V5QE>~BE*p<2g?_&EN9G?X+6>MU6lq2$67c2Nc;GMAi%8|O+PISC?% zpm+;8fpI`Rt8i&i&^x2=Z{fd>-d@m$qkT7bEEpDtDiwUJVIll6;}BWXj5Q?JqTJAF z2aadnSjmZ`qJahNkTV_lUH_eKu(YD^QO`viEh!HM?FmkU2G(Si8qbs8Qq-=i1J7i& zBeYB9 z3)DS^)*y8gA|;^4q--tMm>`owo5){N)h`Z4Cr@#M;!IR=?E z8e2chzGG^^Pg56TqL*NhJ9If!YlvhLED#>R;+F`uRXfDoV0!2WOCTr z?R@}NS??rKyuzQ8UH@GiIJlO^O=qy4`?gV}EXie5#t(p~Y|UQUN> zw6+38MrB5D-EbuouzB2(0plTghd+H*;xca+%7RX9cimj0E^pbx{&7bo@qs1r!Cj9) z%S~`cXb(-v&2Z-^p4fIx896C2kL=w;@g7VsgQ~wyWD_u zvAPWvTHxyQc((s}WgAA0?{r3Ysb&Ick;aDl{#s!KrG8d9Dkf+q zWCdi=C=QOl`?1MY2D(%c>zYc)rj*p-d1z~yJ>?-4vebPmkG0)NKB|jM=s8 zhxl3=uKLo`j!6mLfLayjS$roVHJj^(cxlX)iJP*Wu*L2`h=W?Q8l6!IM>y(q+XE&S zKI~fFzfL0H_5^PktPyg0m-dxfWxYYU27B@pykWftSL|zEK)*=3hkn%X-4#E;bW!;R z&iB#W#XcafBYJj`9FV_gFuZ9vKJZ$B>yIz(K}S|)Ib72atJjX5g8Ql)14o z!_E9KyxS&+nD}vrzh1pzvZ+`{*Sr&`56#91ed96*=#uV#>ZH@Hvb2W=ZHYU?DYqL( zj@??-yIw@n@Q&(v409g6CDywZ`aY+a|;GL3bLqym7_p~>5fc$ zY7a)^T8!0?2tFVF=1Zz<_am0;2@WvkDv&Tl;Wv2~v_CSbCKpOz|z%ZVm z+Ew--Ih?4_@7_dJ=>bh3{2LNvQ~G=6H$y#1TpZ174_7@XHpZv2Gf=cOShO`+^o1z) znhbk=hJ$ewdp#-kS{8eKhrMx!gR$H93XxTG^hNA}`u)*MsZ~^yj#Sk!kY?3wBikc; zib3TWZwih~Rm^So$hWWdStH!OK;XoC9}OITzV|QCu@L=IZ*jo z9o*owJBd`PoN&)VKd|CZv1vE%_yO(aXZDy)G@LEj5!;1)SFF=j8$)EThyug#l@+0s8j> zzg6Z+sit@$DYx^{4id_U0*3Jz`oS-D(rSt5)6g&cc>_-x#v;2#F{Bs>WU3S%bk!d1 zB%abL?%bm?SkQ>Z&l?&aQ615<#>Fb9PK(Bw3yZMu%ceso=5MrFSzid9L$%UBH3|Sb z{q(OmuwPyz5oqt{fT$fY9*H?o(bXgcI3nh)<(oAZ<7alC`2#IU!u38aIGnpyEOGV5 z;5c&Y+~{L?M!`EQoF8EM13RHvaa@^(Oqbr!3$^!;>_>aUZ(D+xw{B&xiSi*i?a6a) z`7^zT*RvX50A+V_4+lN=y0}qcA#!2S_sC|MnP12Aw-b7ckWA<^j&W9d|!9I+~m1Ikaa1?uniqcOL&Aq5UDQl)sGD&$Q| z0IF6oU7D*_`w)Vk%Wl6iza&?VXK)*url7SpwyZ_+70>fIlS!ZyMubks-M0wPgKA)2 zDq)1MLD-MbUk95t#L8gCX|bOAi*KXGV`U?Rv4`LuZP+TKEZE~^hmux$#XU73+_hDD zUJei#t1&3CVyYXyLH*DZ=BP?7Vl_dP&K&VYK2y&mi;{)To~I?>I1t_nJz;lcGbMXu zzRkEk1=*3y@LCq^j$O0Rm*&|Va$Nw0&Y{CJ(N2q8f&etx(92vx7&PI~OCJ5LtJtXL z-vrBC5tYq9@k<{=Vp-v3S3vtvZOFBYU;;84_iClE0Nl)f1deQwxpRvK4%X4#MX{i2 ztPXZ@Y`DD(WdiA%ByIwdA^0pbZc12#9B48u)*njmC&Bh!PEpnIG_q6YhVLH47hA0| z%N{nr&4xdBFv>0lMKwh>vXVnY$Hj=I1c{~uh^9n{ri6&5#E58wiD(3gXatC8M2KjF zh-k!!PzvHCXT?qIi<%K_X94YhO2z4okgEkM{hyjB+@)21BaQgnWlOnr%gq*{$uJ*n ztk4eh?Zs1W&~ZY)$jJ(``GzYCzXqq0GHU$N11zrJRdXVECUexkiY=K%_StxzDuHaVq5I`m8TaQ)^iI6>ZR7nn)kEx%9JK*{o-;0;AS#A9hVwD=z~g znm+B@T|(B_W`qSxO|h$x`VDx}0#TFq*)877zW&at$@d8z2+JHF*8G=6#U9%@a=!2_K;jC}Cu9Wsrs z>^+3C11u)ySnV_hOjQuvm1VSEnqRW0(4tI0gtfsqSxRco@A*dZqd=dp&v|Z8rTvK zBMLBoEA44Lv}l;)48PU2XnaeIeS`g%Mo!3&Mo##L8RY4YMo!0%qTj#O$g!6;aW%0f z7Id+&cDAr}`j z;Q`gan1jc-W{Sy-BpCL<7>GnO9z>@bM>qK3A0|KWk7O8@VjRZcOS}>1*SGN+AzuO> zg>qRaPjglIQ*XTy++lvUR4%}%;k@ZszTe44BPDlv>gCyVnBLK}*xsPU`~+>a&(2KK zo8zYQiBqIizEPBZw%Qn^=_J!3{af`s$z}irpN2i!RJd1;;dfbrOvY zvi#3kRm26>>OvJ~g)3=xt9)+jX(uCaBbv;H`EpCOomL~^ZKPEVi1C3)GO@{-E60*G zX;$kfZk9+%p;kt_RsEu_@7yvKXv1exM*CQ5v&IDEDUZ?l(IBbF%696ajXcXlvu;I4 z;uxA4D2Gyg=k8?Ks=rQ+@wA>(ayWRI>=q4%6ln#k_XX3$KC*Nz7Dt&rMhpoz0z99c zC5QwvN}>Hy068cMGy}RRyb*oBeqtYbfCDt7IoB4nPFnoYs z$t=1=6hZ^p;-4D`8nGK6ViJ4-^xbBZJ2}Jk`y4SSJ)2Aa)DP%y1Yy)!N6KBuym{vV zXw$Z=VL9{@JS@D=UlbfX?xDS3eElSj#p@1H@7f`eSbG0ztAqVg^6i7TTc_)PWSV<<{!@Y%2%8&B1U(_-!UIZ%?*L7%8%{v zD=qy%*HvUJbA^@;LEDvS1f_U{8<$IP`B%T07AY{vYJ=&s4S!MM41%&eVtbgY525Pr zlDL|K^VXbsY#w?;rK~b2pdwg6ALjS`H<|N)V&+hh88ZGSUebRQFiHO1ywHEf%zuVT zm8zB+k{a?CtOPjp01imyia#bIy{@J?NLl!7J^&rL>V=K?FuQB&U>Zce&0`VV)7`G7 zj?Zk#@)E7uPGgg~RZ4#ZoR8IS`HgF7!Turfi#r02lSyy0YrEg?7d$63zkPp0>!Vdu zm=B4Ahz77@4l;o7V%G@c$dca}Nq=Q2+e01*WF}v4CtXh~=V2fTWU9yq#Nlr%z1;YK z;Oz==yo=k;5_>B8`MbkIfN)NO#37fmr!q*d)M5j;tkyew^)6zIozzdy*$6R>xNI;e zE|={I0q)oGKk|<|YELf5C$fZY56nMAbp9H=<6p24mnfGAa>i zwyWhjPKs-$XVkg)4N3~@QJatzD3wtKTUaW*u7_=iu194{7a6@Z+BVbOT+jq_mvX$x z4~KUcZ*0h=L|rl>YE@?m1sBMqd-^j-gC{;?B=0>zy$IqQ0Dk!?`!`w|1sBDb7L&TX z7Xm{u4=OrP<|=?yJHdTkc?1~PYD6($luB$pK432uw>D5L#zk!|RvJ4`Ho;IyD7$D! zfJ;l66g>mJoF0PkTp?m-PVNKu7fFfEr`xnZ2~T&=k}9>dNTOfRmtCopWC9GW4tQu7kkdNiS@B9LWE zG7;I31QNlGnn2i6m%2>Kwv}Bdb(9*@sl}5-Mx(jB0ivcXru5FG7&w*Lo|x?*L{kd6;FO8z4Z_u37t0w|!fudC>GbB=*s0rERtDk2Dv))`;FHjdjtnCZI0K zC5ThE@<3g;V6&TY3j|Pwno(6P-CqY4owlr1wQ)Dvj73wAQ|Nsw0w@uz$c^MFZNsF7 zyLherDB8qpWLe%qW%f&ZHZ1Z8Q!!t29WRps8!}~*^&l-}J~D@3`max;?;cl6>72~R zj&>qpd<-l|bC9I8sM1rSaT!YV#Qe1bu1?2=I8>#~X|%z4n72uETjx0Y_NRfrO>VRs z>y7V{|KsW}zbNe_1Ek;92-+t5 z+b^QvthK+fL!oX7^mYHH!O);Q+9OExFo1Hk4G(6lkdLL_ea=pA$Wam#Ry+u z;2+_4A>hM=G0(4WY?VDxS#dBO&u;@&UmD8X!bjWuR{FT(GR%S31)WPfn5hAb5#z?7BE7 z9AQ>_-GJJ#BHfdk@s6>fNs)Nz+0iE3y$sLPotTxj%p$+SECI?XJc6^B;pRR`7~{Ga z&PaYbz#Fkd)T)m7jKzPION3f?ZfXjF7GB>t2w&~7UPs=+Xy=w;Ej=n z8*qoZF@1OFMd|Pk++~h=$>H|RI3t<3{^J(h&ZBx`8lS{X^I?3bjzb`tpKijLldlWw+!n0S z1=OSNn}6j+yKLHWSdVW875w@-hT$3-_iCPiusC6kEZL=siF27Qb}vJ&<7BS;w{TeL z6e4RX58>XU%YyW}lIEl`bLfe6dv97ad6zyWB&NuP{demCu0gI}joF+dlmK7WtFNEu z3{`-jyilXV-~s#qmG0%OmT<=TQ_I(XON9Qzoa$GG*6|Oa=c51mMf|^$x{8IZvy6fL zztq;$Z0wbPj3KA5y1d-jq`>{8r0b#3B_XiH;hhC|RSAH#!NX+e1K~EP$AYMdI~?4A zfGHpgHHTEIG_i8;ii#~Y>uB_G7MEq~md`?L%+}M^Ww|~RWjAicY|J=;e5Tvj+=z0G z*`Kp(p1H5@JFmU2zE0<f7XGH|chG=`z5K?{l%a zjCb?!yZ_LQ$Axss(V)LXWBUrT#*80J32+CGnA`_icT;DO1-w888#}49iWxgC_Nu{f zlgP(6)R!5{Wh6}%F`jWDQUMQI`Z+wNIn(AypKQeQd?t6F!kL6jk9^mrBuu>U5#+K} zcKK|9UYmR&(W^2uvsPNE6Lh2iH{vYw%l0;eoqKZ?0X&h~T5e`zSq`q1-r0`4sbIoy?_8Pk(hME*(7xQEUiXxmi+mc$&2=wFTg_dP)$w_s1)9 zCdELxSC}>3-n>btkkEHCBsHhMd9|poxs1{9U{lykI?vA$Z<*|1EZ%KV_-8Dqj@ee6 zPhChnJ`kT1Pivd8E~V6T5G765$UGsGsb<9YI^@uaL9mBC8fx{^6Hi%h$pwe#y|B(-QD&~rG*)GMCRTCwpQuLl;2*2oeU zcFCtSv8?SFMUco(z6NiVY4av+7cY+`9M<`KUPxEVYTIbH7hgBFr0CvTdmy8E+;{mr z)P|AQtJ;~Ckf5B^#V^k8)>$RqX+Bbyb=el(YmA9$R!t)ioQ+EzV=<-SeEL**L=1Z~ zSKYj}m?mU-1QXCakUAl2%&g^uHP1f=UUnrbbqJO*3$g7OUuqJ)LfOigIC+>!C@d2W zY!zUt*(Htw4Q3Q7pV=6XN}jwmppID-nJcD9%b@|(y7W``uCS6hAJrm7iWFciaS)pn z0Nc__F2g*`{j@674Ib4!B0wWtO_V&Wlvm1@SR2YB2dtcaXU8`lH>lRDNx&0c1SU9h zyK{Fujn5(2iAth>v2!WHV_DZ4xRorCK}=z=5A&XMi1tahAxaZ|8c=s9BEe-NgOq)w zE&)@1PHLU8$f9DgPakM9eXhw`nMj7iJ2IB3rb8Iu+9pqV1Ca@`hba*(=28Z()xSb7 z2hu~$!CRWRk(LXs`r$5@Qyt9rE)Z}Bm?`5GVH*&5Ir@7uCb-~nv(iFEXUvZqG{(`5f0-B7{1+`<$kb!kJ zeM?23`&+T_iV4y?eH9)PO|=YCGG2*?wLpNfH^GFl{EPEQO-IFf(h8e;hWvY!A2D?o zdybJ*KEimh9Sps`B#JWk~{Lqlsz3i3+H#w7}H+FM0&Fq)<~#l~Ai!b25P)hF5D zbkageyzd>IDfVG=LA)hv5At_{ebIwip{Ka^anF?!WQ;m7Pdr_qc$%XYIYgZ;4#%fx zj9AaFj!o3BtZhjNCG^(FakkBmI9_CRf`&}nV0j=0F?!f#uglB@Bf|ieLwaSZB%EP93C7r%Q5Zx^1tA)*V6U4Z`phA` z{qN6BYFYWpc206bM2FTxMJH#V2JLgsg88g5W3yQE zE=u!GBkYEPBa!BkvJa`icNx?dyE^S06AvCS@*NB$nhNdRicRyjwWwqlTY)b>Ah#-- zK17cvkjZ;m7&Tm@TJhfOV*$AHvv=0z`u@bg3u%ucT-`JH3jXA;CGQ;m9eoa;grkcP;CIx5V=>#xq}mT!g2Gmp%H0AMvL<1oL`r49a6`kAnq9fF>IIgR_EQ zRkHI(I^!{dq81%W>iMg^40IzeN5}57Cx!N{#_70MSK(sOxut~lEsi;^*Ww~3#64== zt>jWm>pQVgZW!-9Ci)+~($&Fr8e0>0m$GF31Ak$k?L)%kD!`vc;bh;P75cg#I<)Ru zT%SOkm6K83MuUXWN0QId4egMtz8rw@WdFwif)G3o}__X9UbBNr7+%$1Pl?;sySWl)G)5bR|- zo6j0wdZmuW2`>hL&Zh|{Z9izYYrAq|zXHR^XLTW!>X6A2`Wc%9NO}QkA~S9nV4aYF zN<8Gv>c6B^^F%z`d;vt}YQ0L%7;?&mitWH9RFXRjH%8=*J-U3NEf$9XP5=BIocdGw z3o74q7hBR$z(PD(Z{V=PV$zDGi9i~+YQ(hGC>rv3{aE1pNFd;sE@fgn^8#KzbTIh{ zu|gPyA*5+&S!lRLDpmE!R6gXRAt*12X};E^pr)`xOKQ}oA?y`W6Fc$Wo6yvVf_>0T zQ+g z8%#T;22i?NR7%SoLNuKyI!1@XlQ-yXV48Ar;aeSRB@zo-T?0t*sD;%CWHV>qvcg)O zp-8bWTo>n*me9pd8@WxRo&9F=4r5jNb)Nzc1iBTXrp11Jh*=_{VgUqA>4HNZ^Y}QwN z0EgyoIEE2wj^g74>*wrEoCppGg90b&bp@$I#1@&(RCC3dbA>Ahjq4y+A~sUpAr`}y zS|uv`XbfqPY9MU#F|Y=4#KT#wknfr2Z-6-eQ)fYGu3$fI@Hj*Y2C?-uwhNY`DuZeFqs$1i=tct!8Jpc;+w6UiA^wiI|A|&Dns@!A+sm190amghk3!**6 zvsz)f$Z$&nRH)e4i;?k%1LGI49sd@LGej`=A&kx%W6U%YjX;WsN0RV&b6-j)tm4-3_f zC1tC+MVs`z=agg!FFfP-Uf=&illzz?c_Zk@vQGD>XioZXz7uVYO-wCpO^pBZ zOED-;iVjEtJ$Pq9mQJ+ds`1Ktu^-sLZxtTGLOhW)xnv=LXn})~>9T*AZjY^%nwa=P z?zmRxf_ll7MF&8vw7r3FXKSmlhT z{Imhk_0R|3brxnl5`!x=WtH{1CERd$fe`D?fQ`t5^r6V}i7j(@VSU29g9^AM;inHp z3FRQ+k%orHxEG=^u5%WOz^DfL5L<~R-NCZ~y5Z11r!ml`L_i0qb?3>vWnL3}jiQAz zM!6t4^T@fM2)6@X=x(7~=I?e99-LrJHeX2p)%p0x9l#zY4&Us@ckueBlKXEr(!#;T zMA^XXUmK}prG%w|?kj8CK@Bw|-@B{}PY$z)sAW?HVg&&ZMO}EU8lTrNlQR2a_h0X0kN_vRNS_c(#iDTNCU@QplZD*w`tXDW;e|2u1!V~0GQw`RGCF^d8yLi zqqE$M|F{l3Zbu%FGa**5g_367<+RH?t&1OEKqymr<>@u3T8A0k94Vq!dJ+o9`*vCPtx}d8k&@7`MyKwgg_o~wsYMXO) zB-b4HY|bhOYT&!NY3qN;Sj9z|y?A?K5K<|OKGh$cnykr1bKw5Pp~=0N7*Y99)eqF- zimHyAtWX$Re_iR-YJ%V|b9iox1)}}56DXR6xeyH@dXh_KR{q7+u@$RcLP9^`;dB|b9+5_*txtTD{a$SKRNUy;=ws<)aG{a*Emc^ zX?RdQ9V%^F6AE2(^A)l9KD}jqm&_r^t$IlV?b_YC29-j!OaYG{JJ0z-y zG|Gm6{^>4_6&V{-4YN1$)Wq73Kl#X?8e2Q>^V6r1wMqm!^OZaTc}NjMU*#Oc=is=< z7CLJoufF9Ld)ozGW#$0DMOekf_>T4ssB8ybCPs>JK%&_sMZ;NUUFRo*I3nf6M@PZi zSH*Iq1r${mL*JIf-oKy=m14q3gRm$jWO`+87dI1no}1x`HjJ9vKvH!^oiLlXu7;;THESNl=ntS%blHhShV%Z0+7AT%?!BEUz2?ZUR*Ikf8_;gm(}gmz8<|#{m4P=ollBp@TmiM=5y7jFQUZYSO|Z!F7>BYh}`7ieb>nMakhB z(6C8_{+BRLh`7z`rdIZ_QRPi;s|ws_l`-zHcLe2WCh2|rD}NAd54vqjCrdmt0`{- zhQdbDhF{N^y;~?_FkeAPWGI*QEjJdEwJWpbC^EmO4JD+%`zt2^zBzrkZe#zsg>m?1 zt7pb>%7KbuXUJTDYR=L81lQ3K@mk~_d|m3%Lp38zn0bauXu{v_mv~q25_UP6rEay( z_?fGOa~w`?VJ3!&XPHv14`hEG25{Tg= zwrGe;gJ;X2qwCPz>yK*Ac=b97JwEe+I}$|jw3-*|0E0i1d=OJDgjsH}uUJi@PKIqK z5)E()W4mGFO zm-1<;Y6C6k5HjZd%2?;iLfNU!qp@_?deJ|09gJ>e%y9gPC z7J3$6IVLK9h8{%Wn1}X|c_}^5t%u7|@@rv|s(r_-Tn9cL6LVAMka@X2+y%lvxR?Wu zPQUC_P{e+)!Yc=~frzL$LJ_beYJpemZ8q)N%e}1$Vaq*d zrt`M>jY@w@IX~LrzhT=1ND6v{*$ZlXhu7JCf8C=EqAos_gno;X1|W*2ZvvP>T*7-Y zL>9F2dl3O&5KbQ;UPjJaf*(8}$%V~yC6f!&51KUYeSgiAj0ubB7 zj?9T^mRZJTD`N_X^g(0-n_rRX8BXuwaF{trPM3_K(SUDo)YFZol0gXwWVKrX*;xxWfe)Qyd}Dx(1t@sgoW7zGCL7^X%UC`Vjd< zxg)xC(;{e1K4ZpKOrTd7dgjQYv|)|_3nCwYwGvX9A*xj{@Rq;HJofOP0AZi~j-Jk` z%`lKR2*?Y(1N;j#h&b+4`hc!!cFqd}hLCsbg^4FH#HsL^n)}Hw;UQ@8G8a-gKgI%4 zl(DRonv9ZsHy~~R+Q1lzT#YpQN83jnQy_<1?jF>_^YEyY`1m89kGRQi6!eK(V8saI zfYeI^lP})#{`=Q|Wmx~TR3O5}!9{*(JK=}6|BbGunxlcesDY8QoukKp=2%^-QcBn= z$X}SAr)jeH&;+rF@oOKNr$(P43a=gpeN_)2V$U`cwLR653n!1 z2>0t?EVYvDbw^@y$KFyXKc(sC1O`e#r2iSmaM8tSe9+ihK50^r%0j}Agd(?CfZ4J| zlgEaR0*CLIl$fWzUV^FOW8%uw5c(?|POQ>pDku|GnmqlblV>h>ZUHdWRh$$#l|JD~ zSu~tl;M_lda)Iu&P(^CJplL~R33BDa(VF9#VzIiOztz6unF%-PVnv5EqF5dm2_rpe z4#A~2pQN~OwmfT#10WJ60ssRB0KY3mHpvlwb3srG?{+*0U0@Cu;<&DA!^6-xSgCRa zDB*=fkzZRJt2^&XQN7((M6)T|0qDSEQR+HOm?S19MDEl{R#HS=^SSO%^s=kck6(#3g$k2PV=J zwW;=Rqv>@WIp~On*!@&R8FUsRhplO4;Br-il1ki48ZA8=q^?+i|B5`FfusPU0zed) ze-XGIfOI^e|@YDF!LE7C)DRrOi$mMBxBjmn}%=GNXBYu+FY2 z$3QTTZa4#LU!cN$^Lq%H88D)xg$7Zl=cOH(=OWo!hfp(#VCo4s1K~)By%4tqO&&19 zdqS|c0$Ty~n6=1k2^7hy`&#^uId3r}vjqvWs57MG6i|HtzA*u@VjJeH-C;&l5%RXi zDc9D8&nR0|hHd5sd*WLPxUqDEhFJ8n>|m0pz=iX%O2>m|#PTQiZmA6@kL#QZ;=2P% z1v9s!2Le5T2_gx@xmu;=CY~9h&s!sKHwSz?MduUZJ@I`$) zMt2jn#SF&^mF484WwnZ+niy;f3apl}FG7>}WY4#V@6p9sr_F!IhB%HfTm&KB2|{?} z1#Zfh+sA|9-~Cc&U`Is#)4N`$1fA-%M>(UwGmKaljl>~Lvia8Hv5hj*vG1YAeGR$o z5~i$8*wV#?c)Ue$i8-b@cO37UaY#tDa#Biwe9oTs2)WUB12h8f+Q=B2191qIXp}(y9U%UluwiF!?LKQ&=6^mGAdWKauTRzyq4ljzE=E^^yQtYqNOkg+cP=T7bes%oCU?1%`?H@y4hZ-mJVVq4%~eX}bq zPf3T|bM~5D51$VReP|*a0thtFW9T?XF@AK1qlgd_=%;yqtiKn!sy!YNq>b3o4L>ZL z5Bj}9W?oURjSkattIjOVy^3S99}PV-DRl!rvr?snXq;E~HL0iX=ZnYa?#a7FHd>$w zc%f^f4vnq3DQkDTjh5GXavw#pn;@GD!`LiFWjJ^hLo1SMFcWi$a{?WTlh&qgk{NUr z1(l39v!Td){Txm6BcKqu$=aIxv}XZUFltI3l!ewz#7leC(LFcQa|%}64LUN%jC@O) zu{@;eoa{Xb&51EPNfV*<)+C}fgKVfg*k}>WgoufHaI}7@>YRvE%r11wj6iaWtGnhX za09p9eIu!RFe?>oj)x8^TB$Tr!c}5L{IRqG8{?+xoF7E+TfJ6IxLE3gf#i^p^uz!L z3P9s~tUN;m2i~y?cb^i9gh%}!5tNp>k=gH@slx6R{^`qjPG*BOv)bz1k4{~T{zA!u zzKAVY9r`4y0@fy#GukD}N+W#}FS%~LTuofUd6j^-d|L5I#S(}r^<3l$GoViDbitWh zB_5TP+aB&8ci_U}3X&JzqHDr19H_lEmD!?|PMaguz+~U4S=>!&)v88`cwLSHvyoU% zB0V>H49x+U_T#CCl2RcuP5ZDfsH*AeDBXClDjnnVT%};DMlOFW+;pYA8GS6U(jWQp z-RQ*KyfWZx0Pnp~vBeOgkeiy09&#+&mAeK%A#y38>eWy#Phqn;L`=Y|mYWcu!-8%% zM%OuXA)qLuMqDvC(%BFRVTK?A#7pwxF-{?>cq*O<;+2X(T;AgVt5#Tcs<8}a5rp=$ zDxz!J2gM@VaD-l&&3w#MWw*9s_Nhoyxfh_nJ6W-}oWp3ch>z&uZ*1x$R@}D8}FLP6_N4phXP*6}IP+3<{S65J2 zQPAf3&b$0UKv7Tx7@3^P!Fu7(%)w4)pYOuT#Y03ZQPAq$kNNyV<(A1zWl_*<``mf| zMM9ofK~d1Qk9_CP&5!cQ%uHdQSa}CW1yg}AUS$-bfM4x?){)SW(9+QOy`%l3y_3Cw zh77fU5~QH4|1Bf?hXza<0m0CJikE9Yi}in}0RvlGJ7Qc39N$N9%m@+U$2 zR}Cz7LUMo~IruxQd2U&%iVAHX3GS162( zwo)&;h))6vE1i+m-F=$2xL-i- zWToVp1d3((8RtY~k}3n4{hd5RcCyC)7+xP%YO6Fw!-FGSaoTQV+_2!^_><=^ z0lX;H+jyu=ea7f3Q6ay9w|Mbm2n|xX^T)hm%RX}svfy=}-`Jvkg?O)i{7%e~wx52z zL1RdCEH#o=XDT+~>}pQ$6>@u@ZK?cbEK@ntArOJO}H2w3(6*WCD86XZ@?ky*Vm+cGH%vi~v1^{|oYY^8XF_x33pq`)D3GE?ie0W{`2Ge~{14 z+?G4k{s(!ywjbmLa~&-H1Nrs`(*HmnXN?*5OwuBG`AT%<5PQgM?U&!Dfn{d;e1qho z`hue%p?zb$@E6NRHOvA9hFDGKJ$(*FypcbX==wK)jB15_UoM-sC%El9k6(bd1pYxN zcEZT(XLj*Ltv&-$Fy*JNJ<}IOFYa8-!9iF}PtQ$hAS$ ztL7p#n?6>w7nIitVTs&8Mm3b`a0qVODhJJ8&T?$6NE`c2<3iz51E>v+H$Z{Xg4_R5 zsw0cjTlxQuywd-H{LBxzzz_Fa_Lw)VTk^QamWSkngU)0Jsw!6|k$T=XMj5TvZ_$hu z|FBEIKkSka&>Zq7#KbgphmFbm{qgh1ObXBo*OmLi(;Q0qMA3|RmY1U|XSD61iMbB1 zRXFWMG1tZ9UuT|_>7O$XXPqqUT=jG2-30ij6&$nS;8*cXhRY~;DwLyGXvhiy#i*nX z^#-oj$TQ*{9>%%gBGM2zNZE}F-{J1eo5E3{Jqt=gZd_;4*vXRv8N?j$YG&jeW{mZoVb6o1vw08Sm9?zsyhWUNwbHb0b8tsW!x zF#b*}1y`0oDj!zi2pXwkk(E*x%Q6b7gNe?FR0fB!HsF%e!v~jX^!*=v^HSVrMfY>w zp?=alj{n;;uk;Vi8~sn#>5?6wM-G~~)XV*7;s*m&)-Tm35R8--w*d)NTm(iXWlJ4R zvQi6ED&xikg6kC`utn9(6NgT|UizHoS-xF)9wGY!)%b(|>V2(T>2%OEvBCGlg)iZ8 z|4RR$?=GUrK9%78I{JB_(z5eW#%Lqapa0l_`Wj{_EjNK!A_YDs1=;MA2yn21Np_Z` z8A=r+nv@L1{@d`h7n~OzEE6S*OmCCx0z*?`93*Xq`ByNHMokeY(5|@!A$P7*1lS0Y zJaNObRBnpw=f+7qR9e&cy!BkPZRn0bsf@v|#cryqpd6?Las{TAeCf}gTX;;Vh&^{g zBG@LK)Aq?qA#ATOxwM{G%0S5S&81eVk{kENVH1e+()%q_>ws$+QA$LuAI8`1{zHsu z{`KE>;h))noW^gIVbCAOhyVAi@8nD;;OJ=J@nbt}?`UFfV(aw(rQ2C*8*12(INy`? zY_4Q})_@F%M8o3AAoY2-$rbUb;4VPOiiCBRVCees25wntBDbhbGM$Z0+vlH->rUJy zBVY#>x#m`MaJ-GUkEdsNvn}24$3mAUTujgt^@Xt^pI^2+6DM9KFC)MCzL5FJwkw9n zhY`*Fa0lE0S!S&qa7Y8CAsGTQQ5{8Fr3sWAC&|PiA&?#P5K*lOWD!ZEq1yO@!2%6L ztMR1uiLQ|HLJZy6{iyVZZ$m3%!ap=Tc(F!|9Jp~ukQ~1oh<&4-?%Z{8XGU&}q2(w- zHQRLNA|$YtX&Wdr zg)mRVHvGnLC535E(81y*gevhG)Rd{?zZGvE;Y#D&TarDU{)4xi?0o(gP|J!A@>04+ zR1|vHg7U6K(ZZY5m1WUsKbb;=qJ=aiXHYo-srCaRhz}L=o~o8MhACJ8yCH2fii<% zu@AO7P_H%FOodOOHWwZluG8PBC0-J%=g#OAbfH#>!Oxa;IAg4) z@y@L!yyeCf`nt3g>l(66OkgCvm)yJ?_BXo1a96Yufu_xm@VhOXIzRdTkOUzOf^7xZXpnH99s=1oV= zRFAQ5l1$LzomTU0q3QEqICk5Vtb8z!=UR%bcILAeou6Hm7UymNu+tH~1W}uTDcpc3>OwKd z{%g;~YCzYlk9Q4+Xnh=v(a0EvbfsZaKy z6+E413&6iIhTj#e70Tf^e26zSF6-R z?Sd>`h&>r1x@og)QcxN1FOBQv1pc#rgKibU2xY-{3lwu*1l+wX zo5|pkLzrs7yoCU9nfp?suIU2ZzS}1cYk77htX2t%7b?~#Q%=*mv(M{qBHqPTP%I06 zOBTSNsmOHpncDIa?Ozy_a`#8*wq$NV33F4-ftzvG6%X&+qHs9(!r7Ip?z7_*K*Xi+jeE zzeLzq1{<&b*vzr ztYw}kFUadJ6F`p=1PRt(WZRH51iTVBTou@(ktz;(Ibet?;5~(@R~u-|cK0Us`$Zl2 z)kl>;`1^%AKqqfXochPv1MEHW!0IC{v<{Zx@pqx>0@|H6oVLHaGsSLXP{!Fxw&zLREr7g5&>s@&zye`eHES-}yHJUU_ zx)KR92{ZK@pJPBgv++-i+-LGMq5MuW-VqM(!Mtzmu4B8p=(XQR9Fj0h*@M>oHn-)H z6*-aHcn8l&Y{}zCbzj1{sa}H*!S_J?lAK!s$Mw8HtB5@WF^%%Iuvs;1N?c?0zlewL z*(f8&XiAK^_lv$vwD?Ld>0e^+Q>%h%!_KYbHtoV*^!uCEW%)z4Eu2)>o6g|8Pe;0O zViLHfm-+Ab|EnSYH_6XuX=MKw&B_07S(LG}`wziIvdSMhWJQEeIqeRB zt{`=u5VX}cu zA}8~=W^Q+DBe%E52b>{>oa&8nW}he$5-br?M+tEd0H&@&@xB%cY^9Fewjw){6k(ww zZx9lV4Y_qVstwK%$?4l({f#CE3V3h0TKkC+Sem4O8aXu>K|Z8dk7{jc=+}3d9ZMzK zCXi~fRZ5qbHR9@xyt8(aF(@YNSo-Sv)>W!9f30k>SOI2TKe{yU?^}6hw=xp{)RLLJc6 z7d`|!50wav0s&hxXM$yx#&2{kpI{0O{)lPd7#AvqyDa+LDz|B?dGM~hn``D-EbV)J z22lM%2@u3NSz+Qs-2(>MRbHf6iE9C2jP78w;nbTyxIW>-{-jdev_ zombQ^5Ykb*8B_BcXhDUmoo+urP#nwAeacA1;JsHpGNfI8D)1p9U%U7A`Q82JdB^Jv z6&LDc{_U{rYI9aZ-QiPXngP@UrdQ2| zgqhdE?d)%`kki=${C7nHcYp*Qu~nd)pqY9L&~17WL`mrK zR9}sNv%62}-`hCqB-*E?|0aLp59dp(2{}T5#{Li?PvG^W=4XytJ_f=bWLv}&=ERkil z-~vF>YR5M~63R*{M$!apNyVFQ5LF8Z4p}fYfh@|5$;55LI`o6t5BmT)2!aK#Od$FM zI_bpnRi3;Y>*w!qGiMiBX#I`b^}K%md&TwonOj>6q!A%qycUedPx6prgs7r-d29%8 z$BOqh5f?NgTmj=1f838?_;yA&ILLeP1Bg041aT;7beVy^Hc~d?(Ub=kGKEZ z5DyRWwhUkO6c9G*?lKiR>fy8%O78w;f|)b0=37X_u#w)o#RfGyOc~^sN;KP>Qd@DjRc?jVND9$xMW8 zS~SkE`4H4#2^;W&B73HsP(o-RCB!)8OePm**+5=G;x(lQB$TAb^i)=E%A3dnCZiJV z((Xu7FYDhbC|hxi1vK10oC)Th0hw!JY^h{1`QSo*CfBZAm?$6;g*)> z00NPmBu8{ukhVi+5cJ#%>$hl*wpMB{lxfO4&$aa<0E|i#=bcN+V(r@_`0&G96s6UldyG{xj515*bkJc^ULud}&hI{Vc)`rU@m-Eo z#Uy9z8$ue!Nv0MNPbHV*H(^h_6-0{%aE2SS#%-fpKkMzihq<;%ZnW$pQNaSGQAsJyr}8THBP2f ztQq8qFsw*ee=J%vX23Egg+M5vWGy=a_oY*An6Sw6(neg}5q{xgf4j1hXyZ)Q2bzXx zoe9_wR1>8@sKWLsV^sbM89LTVo)|%ZtfSnB;Z}4fmfZz5|A`pqy4s@ z3aUoCz|rmxrgby$XwFcxW_*Oncn$dZN00!a1LoT0#e)m}8XbYYqt=}kl5-RY2z>kL z3Ds(`DK6IK~PeAD@_Wx(8cTsK-Z!Zsc8HJdT6#dIluDXoUxYwNs= zNMRz8TZie5-Y*WFk|G_KD?>b)wmBm;{nfITv>WuYPKN80%_z0=V&<&+!%kTrN z6-*Nb{eKM|BXm1qEZT$K+b4bLoDA`v-a+l#8ciF96sZ|R??EhwN?;Pfxwy%Ss}C_%0N(+JeMcuw;Afr2`9hV$(h z@W-+Of?NCAK~o%Og*1qpH}@zVCxw)5Qq~rz+5u_|yP_lTOw;YHda<#{i7qs3m2|(E zDjWZbLc&ChFCH2!+!>9Gi8yx*u+Yu~74MZD%C0Pl)|ZhU`v_~Oiw$N)-Ap~A6;T5$ zHa*3D?kQN}e{V2$3DkE0=3NH%1l@9^SE=xWwiIZ&vt{XkFS0YX!Up`R6${}*-ysawX+u<3 z)*RtJl0r66MGji*624g_hMoJP{}`q2!H+!mQ;_wEy!$bA6B(_YH=n4Ke5rlwysX+q zdu#tn+%TV1SalEOue!zy>5z1aa3h>u38SHd!ha_i{?neKwc&_8eq(2?pg(?4|1a&S zlaqy+tqs7|`QM9Vb;57?MFEVF+|3TuN#`(It`I0FCUOl}l8mT4F-D85A(26|Nty$h zRqdK#gfD7-*4tlx{(ecfKD7Wc(m0*OqlMa4AzmK0cFjjD;_OXC)K>88i zBuEM>b|o7glu9drBoQ~j@npWo|53~b7WCW)6U=M0@Rxw!6TFaC`gLUh{?%WtJ0AU} z1Y%6+s>fu!4&q1Qko;@k``*8|0+SB=Zw~uCF~*!xVuDEz=E9=~$`i(-n?d9XXYT7# z7$U&<=B|v?>xG}5i|#TR3>-3`Y9+VI^jdJSW1l@v>AVUhlLP6Q8Hxu2f5R7m8%vMG zd*n_MxmJGdWgpTjfB9X?r>PC1a?m)@uxnt^(58R|ESLA>2|NSmqT@~^ZYS2mng5EY zgUS4~cvm5O@m|o(uvwrmuX0un%T-BIAa*ea)zNT|s8m^ILaxb|BL+Ek?1ST6*S>5~ zPKpSU-Dm_rOiv{vw{^sLIC1C-&fF=Kpx1R?4x=0qU2xiX8X8Ea+W##aZI`8eVsitsNyO0eXJfbA;E7DUA zRXPbVutE2)(F_f&BmBXJg;JzV*iGJZ?l%IYNPyZ65@L$E0h3G zj0$TWLZ=Cd`*9Z8+)TlW&}XipAcXMOi2V>rZP3=#&A2pXQT~H4+xHBezlquAw23(; z_pdhBqTk$87HJ5VKiAC6w=>9v(=6xgx5LiIeeP~9usgi|@GT>q6~+*`Lsnl>2tFz{P$@;%{7$d6nVP({|X6wv%tM0gLrW4)Qd(J$*UYOSF)|ED20RG0$$Lo_DwDBVygW z905QxzK%NC@@^4e@}^*Cj2duLrK}7rE}c>xwc@JU4rtsUkS;j1PK%B>)2ecdGW46g z1C2pdX;#%I)At>|quI?bdMvP^c55;8%pn>pPB>U`+MFS-oM&*#3TXYUCChK-=}UM0 z`ZE}J{Uih;qznp}ad&-M)qsGvB^Ky+lg)hq)dnlzFEIJSFo@s)QrMEp;x1C0UUE_> zj)Vcr2iB`>^fu{)t3qD2~d=L-NnKKPh(g;>ux4N1Gx&|&jV++*W#pkvd$Q35*ufSsZdOG_j z(jXY3yaPOO^o+h?_OoJvFTH)~<-eA{q!K+f6&x40GkHKYT=6I}rK}IpPs}wI`eBrx zEzTG-WdW<8WKXg0OP{xE+{!2VvhoC4>b|d;B~XD2<%`}*6ETQQZyY{T>b#}%cgqdJ zC^VzTg>HQ+SHYLXvR-=}7Nmex50$?Xbay7&nJJEpGOeQo<_H95`TcpspKQFsCen8f zqZUDue7_nW_{39Qe?Xe2h5_=-g+!J`5vp;r~VhpvE{RkTHFgG>?XN}C? zSS0!L{CE&;h+Cd?CEj1IcMs^@@rxo+9D%y;xPF=-3OB(`W(qdJcw7wr7%4~dzAf&6 zQDV8*$<_0eM?#l$gu8Zie2tvTnmn+^zO5YJ&BL6EXxd?W5Wzng2!YXzx!5~(@(B#u zmf^nf4f)!&kAkrp|D3;eNTBU+yy?mS58LR<-ymp`Hy zO1}vo=@c@5P06rIw9Jbr?M-uvkLb|VgyNBoP`CUEB0UA`E$Ao)=Hu5{+qL+tDF5D= zlsIgf8Utr-qJda%65~luxrSwmRr#%mh)`wNUd!NItX4pnaV{e~7ZsL=u?xvB0r$}T zuvKZOXmChNT!?HA$=$Pb+bkqB7a^Xuzgnl-Up^by82qRarBx|m)7`DZs#9xN=8T_ zgQR|T!T$69!%?EY9|dN z^M{$kP8XcAWy33D;i5J4-JIwA3V^=+l6|>5KL6@{QO~VfAlTtCSX?I5574ybk zWb+$(5jGDW0kgdKJGR3uxdY;={q}KWTYnDcPR4e746K#iepWIm9YwV2Vefz2wf<9g z3YkuvZ{8`-{?@e zEUx$ED`t$3;Coasi!p`ItCI=D+1P2-i90xw@ zM;1gDs5fjH*woJoe@+2bdnS7*1&}3Rmp+|7@F|dE5a=KLbqE@up#GkDK<1zs{>lNS zd0-I0kpZNAN(Pv7P&D9jAU$wda9KcAKh%H;^I*-vx%?UGpiV(M{2}VFG(bcGYzcl2 z1>hOb&Owv-lgxovfy{uefMEMa_i6T#?OE^P?CI?B?0N42?+F<&+auaD=7nBl_L26X z?J4as?K$p2?MdxX?OC$(_OF`EqkW>)Ez_=rY&DPRg6qI<{jdhN1+@k4f%OJ&TOZyP zed9&n-7nGGDY<=)|NPOmJl%Q=$Nm-PS9B}Ko;}I`(=|Uex9!!nhdA^4uv5poHS&7? zMX#xSR`$e!U*&4$<F!yv2K6CjM`6-FIg6FP!doU|KxkD~H1z z0d#qy*4<%w!E09AjS>06L(D^4(JM`K{*w}H!-xC2!&Iyd}`2aX`{oEBK;1E{F+YMMM<@bcdw$`*+xExJzH+VYm5v3keM;(SV_M~ zh+2XeO^`_hx!swWxOy3pV8N=;!PP>SYI+v)Oi0fEKGaSYZyn|qWX60nJ>N)~A;kdl)Iq+j>V zw>=u64<^u~Trf7%zs)HyHObMU8M=5h6cf*0DFMo%CteRsbEl^bznl8Qnia&wb=66z z#MW0tf^1=E*xLzg+vB~P@Nc95?B*rd**gc-xbVK0_75Jqlq=d&96RSCCd5+iMe zQI?5dFSh;KSb7R?W@2U7uW`3SQkK2DOgmuY&E;3&cYURky8mfv&S2}E;JeSeU}eWK zkDd$_i>{Arzh>A->jXsoKVyK4&)Vs0pv(W@N;(K8GGXz;02( z+ESg;;pwDZ*6LKZeJqZt0gvWP0DM3_v7iPM0jGx#vNOLbN`iTnaw|#}`Mjw0mKXvp z(g~tEwACduY^3aF-mPMu8cwYni`SLJ_5edu8W@$L+Mm}Wrd=7>7{Ux$$vkR8!Ew>2 zbGgvaBCo^dJ6B|hrcAtTxcl~G53hz)qAnG8dCk8Mp1#wg;ia;oRpq3oU$w2_a1@$* z3W7Ra%*LcEDcvbUxlRaQD_9$B-|}bEmIDL-i7I(}6j9za7?9f%x`D(TeTX4*W^Y{* zA9i>e=ir*&8FvxHc-Fri&xJ&ihs*n??#$OEHxZso(iGq5D#FI{14i>p^-|GE-j-Jd z{LOs9ISo8+s-VJ97DZ%n&E!~=;hyI>^~`*49|TYIAxoSw?+3O4IF3KEJrGtLSX+Q~ zAIRYkVt*Y1cnrux5b+;{{=fz-3_mfTqd=eni1IKffJQ)&{gn)e7$7;2(qM4FWPoCR zPWYGmqf>xW`CIfk=OLv5O@YP$#el_t#DL5FkOP$i?)fj_D$=Wpsq63cJs7 zzW$<}4%M-u!}5WW6>o*Q;pX%bZAh_hV8Oh-8HLv3=K3lvxsfG#V&VY4HhP2@mlU{M zqh<%G(OqQ4Y~jj0wvzZv(!!Gh4VrvPOR%)DBdu7+3jF7H zsC%VeaY=i_?-JeDjs@avh{nu2A=3gIs3=fig}j<`${Y=__Q0qD3PD9f*CUS@a4eZk zxqLBp@Xk>c-A@zK%3lzqe%-RRIZ^xl;^1D}IJC+lC%j>A0=2?AckX9hMK`y!wN4izK$hI)?gybs1>q%P(BPA3`rJn*7P+NqfYtI=6=m8W{L0@MGUQ zfOf7yU=3yi{ZDwcDP2-4O%3V_JzO3%Kb`esG=-fx4A#bDRCRehSa8qlLJt7wEdjKf z(@IP0{T|!i^ei2)V|+&{_xF24raEYGk6`EYsX#Zm$FLnWGnQ zpQ(rOW8U!t|b_oDE-{j_I`By>(Cr_ z>|cxLhD_WFjHS4xpnT2jIC9~V$=MyK97M|cZ8|(?Y|Cusi~jewqgh>v2j9pZ18oCX z=CCwdcfIi$Fn>wyHbzy*5JqX?@-?(Xo;Xa`b>QuW!e6ZQNO+GknQqAJ{2aWGbgt@) zz0{@tSdKq}A?kS^QAdCs)T2rrna5s{vA-U3&ARkS$L*M+`#2UxUDpk_-h<2zJ_i+1 zou~eWzFiQ1H;_ueh~eL?0#6f_8|h(S3&DGpz(02g9Pl34Asw31{6lXLQg`!ntcHcV zeQDugEnbj}^W0S=`+oL@khFx4iBYZ+9aqA($m71Trux~Jm!*_i2)pyL3_qCM2=f3u zeiN1q6Lp1T|8DllH{VC7{o!$Dxgec->xN;rg5c&yvd$G+_9;!57~$ zhdlH^vVQb^6Cj+#XGi8pilQ9*nXdd^dz{)cK#G)}UF`Ry5|jLd#sW|6hOCXA3x2cL z<+I|buIHtC&}%{XDVw80=BZ_=&W2!bB2w&pjBo8TaCU9Unab&UXXd~Tk)nkKwjkT@ z%Yu8ji2`mH*}~|J60*Zj0%8N*6RVOLwenvn?UdO&`-D?l#9P!6&ywQsrxViArj$qR zC60%m6r3>nHPfc-$)2quaM#`6?6Bgka&*27Hd}GaExVEtU7MKAbVk!wy|<#K^;|YR zvk8(?JWl6#wTZaqV|VhtII8}Nw}?@S-m-#RE_F4?&T}`Mm$oscdWEGp3TKJ7ZKNAS zq#IyJxA35iyFt)K<V(SP2snE;zjsc*t1Z#kSAgB68xQbwrjir_}NTf zcXrfgG)C-@6ZgnB%6(e8^V8Dh^u;q_#n*U@2Zs#_CnZZKnP;Ns9L(Ei<&hOho3!{# z8&r987Z}8LdXf*O>HUkObL+RhCJj7Y;Wpdl>|eU0JVk#FIZfI4MxD1G9GiNgFWd-y zWJ-9I!hITYSKKGB3ssL|!^e-5h`>_%6D5#?Z5KE)8#q$$IASASAu`4aPbui~EO^Ll z2o{w=(radcFg_J0Qd~;@kQZiBbR_6MPjK!S)gB^(dxs@QqO{V?oe;_sf#XZI^Q4cA z3!8TF7{(kHE*3CzF5jDkV|mUbdvG9R%b(Vkz)q3|7YFb7!*KMzBc89ztuNT93zYc1 z4lWscXzT*DC7{ga;p9kyd0TI2Ku_bLMzfAsn(^4WeECV`W`0aFv9%%)y9tP z{uuhMe)7MEEOb9I?0#bV49>GA!JgTK7?0Xt@Migi9^A`h!mS?rRr;0L4OTzurH6&7c0ZeWW7u#nm@tL&lJCh6&^~hwL>!e5yWz-$=^5olbLFjYP!uBNZPSZ1%!zAY$tdq1M8GTSX6p1{_ z6F`UW4Xm3}pG-;4nG|`KBxanu8N+zMI_~xj3R9$?$Ig(J*Q|uZ-2TA zMZ$gaX!+{uvH?3!?Leq1X3LuFn4BtB?ntGC$|5OS$i$jmQYpoyIGv}wB(uF^Ihdd_ zgzi}Gftxms{CHrRG!-T3IW%dWphHEn@2E?eQaSv6fqZ0Fa@rx=8gB=zjha`EZWHcq zE!u05m71BZ-coHtQ;)$uMjXRgo%54O-=nZ?iZ%5#RFcy4c)#*6}0Isr%h_jH6bS{-_c( zT5-I|A3d|<9?+hAtFqsP1=+TG0f_OaoVuGJ*;tU@WVU;tUQ_`T8^sSFy_MuU4EK4> zyJq|H5lAHN`wm#3fSvR3LQXXc~zPgX?HXlO9^_q=W$Jx~% z%8l)|9@35R*BwF}YSVhK9&XZjz#ihJWP!bgrd)))6HCv8bS)k-KG)3GGN`deG|*{XKg35tZA4Kb-prq>EQJj-)D* z2K?=kc`Bb=7U~e9Eu~(z?2xi4s$53v5VJ|uwIH`q^|Hv^kYAl>V1etl;L(+*KBM&E zS7?&G*rxZITTI{+*8KV($WvvxyJG)0ylL|-C#3pc;Y}qwJ7*Hc|KOCUXv_bDW`^js z=&DmBM<69Zp=v>)px7lvDhO5~_#(iAfY zn?~s{doeFxH4IndHwQgI;7BDTMVRk1A$pO~%tMYTx{@~9cFuze%9-aiT8q}*=S52y zi5az=l_^IM?@hMnGcl@50>Eq&;j1mQip-6h<#6jO;c&ih~v88rj z>Rhd(>Cc4P7f=|{Sh1z7o&xi$kYeRK)h1dXFX6K`7bJgbdGZB3) zSCuU*stNqe&SZjHCXH&FvNN{CczLj319p~k zu6sc<;!Wi;75gMi;qBI~UJ)|6&h%4J>~CxU4>G=e)kqkl$o_ib7}*f7^7BC{5m9M4 z4WZO-oSdhbVV!~m46%>?#wmI~;Ldf?BEkB1d}!kC9Gmx#*`CODp~_r_K5(64Rfkz7 zPkY$?BRz3_=0Wb4y?h@!%}}?JR%E-~!IN#`$!F+s;g?l7!fIRs1h^H##J@rsh~V{$F`u&en0PS(B`SRauzhJok7YO#BK=}7C$X2&fMm9t7)kD&d zKtn-56|BZ$B{8T&wGhpZSS}GN3MtUg?j+f)Luz2uyjh6csITrWw^_EV-Jth1=RcJR z$e(h4S224deye8wjM#A6p^+rmDq-+=-fleMxo+pne1H7MQfe*63&0WHsx6J=oh*Pf7b^;82!P>5!F;G#BXK+#z z>_kUnxI!C2*%-|X99b!z8BpVUMUd)-A8QZ(+ zPKXCmo!J$+G~8zP48K{k+l=uVE21VznuSUL(I9ah5j>^&8RayS@`Lr!luov^+)1U+ zOkpYpIQQv7fuc51-Et?2Fq<;bBHJVdYCopz-UFUlG88edvfPKjr6QkYQFPbgD>@Ie zNQ#fOfJNL%jHxYXinSOrVf53;K~wWo9cMyB95?F{Px|3-vj|OJ4w=!G3gp@4#_J7c z=2AqV=K@wyLoqn0CA9xjG{$Y&OlfDqTc1Q#Xi!o$>JI0uvq)kgaPr^A44*~AihdCx zd6$u9XRT7}OC1x2HBNaTnCv<-ey>}}Nrh_X;uWiM#Ew~i9S)Epu#jPjSD z=V;~u!G+Dbsty>uR6V2cRK7!s0k~hK-Z*3OR6-Y3W)4OV*62Srw{(}p)zH_v{FO9p znSoYk3sJH8*osPwIZvL@gT`gB_I%wAb1K&v^8~<)!th;3OGPGyi16xOOc_-UH1U zg?@-K1i8bbc=`z02iI&vqJ%kmRk0p4A=(jbV7q7$#9LUFT!s5GZu2pM8GfE0@b^_#Eahj3<>D^S^kvou#GyMd^QtF^$n`YWGn&jRQ1&PCCLM>=Qh{O+J~;Iec8 z`ug>g^s&f!Qe56GLEB4WzmM!qZ#@7VFoe4v#(lwbIUUlEV*Iazdrt}3Szuu?s z1b>#}6N9yfGU-`9zrYW8lB~{~CXo`Vqya+wqsKwzD55Up?&lDMXSR;r_gWxPQxHDqekMA#OKp6s+4YL(?^DOJC)X!D z6fD(i5*Ao=+mEd|rcZ@ho%xd|*jGzKQj;6O_o#v$qa9s%>BX;T%DADWY8kK} z$ktI8n_ZwP%SI|Y%Zr-x$+(9eWnIIpTsg6=vSSt0*<;=us){APY;i_Az#9v?1s%3Y z3fe^Bwo>FS2wq?hcPcrAu#VPf3IS%?jWNwcG~|s*j!TiNBsLF<$h{?6bzR{wk3zQopNt`pVpUBt^Sibx}wzG34QJj(E~awmUhA!1Tb< zTnsB_QV-X!4WR*WMz%Tace~IvWX3GCm+D`}K#{R$nBHlosBy9{#AP0!%&rirI%F2W&c^J9Q;0GteWXH{eWWqCr>|iUuf*&}IT>b51heYiCxPy3A`dTaf2C zNr&jNRG^K1nvQ9=S^^7mwsxfKIQxB{fRgBCXo>!|Xj1KJQoLVaZqeRIE7GBz1P7(2 zBNS01r~+Vfx12$giM4m_Vdk`3aOL!QTr$jHv(n3Rkz?+tZ3@HUgOMOSZh^T~Y861q zB~;*$m)HzyO4GZmPHGk=?S-hKacoA+l0#_>0&l~qj{cg~_U7;*( zp_=pBi%O@Rq|0P-*sRbb@x7Q!cpV}lN8(JSZ2^mcK?q}o>H*v~4ydiFU|2nDU zfQL2zCG;SFqteg(oxHu+&_RFlvAY8M&?=#A!{&6{$kfE89|(Td3q=&L1f{!F#CSGY zSf^>0(wtBksZf;&cOGo?8**~+d%0mZzXu?k&WnBdDeQy0fhD;Vrm*|neD5yF0%Bk~ znmlsq9A3hkBQ^YEKKNp@TsRL0BOaZh2sWk#pw#Cjj8CQn()H< z%a81!V-Rqa;67NOLynHY@y@sYvWMP*L1hzs$xLv|3oyTPed)S@jUN^D3;*pSYk-UB zQx!9Y=OlBrLptpAcS$Ux3NdRiOhwx1+R3NLG}uDd1N`U~uHashS5aIWx4zh&5YT_G7P2=bYoVg3=yBu>q{%8KLxf zS335csQXsaa~llhtdk^IpGXq@>{C2HvCB7sJEX{ZUaBz-HEI$~6f##xt0iowT7Sh3 zCDdFt`pj+~m*9w4XViP4_Q3gWm+S681@!UuaB{o%NeeUelzeHSwCD{p8z2Fw3avB% z2s$UQsg2mku_hNw{9SFBP9@o8|L;Cq|HQi{pezUYn`lA``Qr!uzn;c~907(_|A>A8 z|HWX8R{QtBr}Nk(f$krZ2GdeR9Q+ww?NcvG3R)i>A`tvDzc$kZTa9gf>MBHyzhx1B z{u7E@dA}+9Oq~CvFe|4~GZBNpG>y~idYbdZBu0#gW`v2-<3Ro2||ko*$7%FqhkhKG(sB^&Z&^~#L|fjPzMh+~MUM`^wK z>@H2$d%H8%?RMflX&MyJ_ey6Pgvm2j+TAiVRx52$&TTKP>_c z_$ndvbw_0}YRi^zgm1{2Vt323RH&K(0z{i!j7=GR4E3|lx^GHGhW=LYn|5l`q&r$e zaX^L1e0NyRo62@Q{FdUqh@GVk{C6K>%~wRv*~OWp1f0hy>vd8^4;ngR zY@_S!D6Xp)klHJm5D2|vXwtt)in034qLxQZPpoavDbK!Fr>3i zcVGLvSZ}JI?F0Dg5+9QB3iz3lI*I7#nPK`{3SaOpZ5P|~%v3yL2muc##4n%DiL=T$ z0kQjLH;INs8Ur+!hiY6vIz{BI9f!>u&i(%La@2q~h)=m*4i}>_wO+tboU4~y(|K1; zSH>XVd}8~g`-*hJknMnXJ2{;glnVhFLSf1sp%T;q-B`oP&{P|CgW&)VrnY7-B3Z(q zA4H}d)ZhOOJ#cp8hv2h)w{)a{HZ+)It^432Q3**bf=rKpl1c`|qg1`{aI85|C&{B; zDoQ=uC-&e2#1FA)9Gp+P^9cZ_L)# z4HB6zFh^z%9WqDA6vkSUe?gEROP22p$+T^hUaaNOfn>i$sL0UDu0iz zCwz}_kJL!QFB)~f*1mzB*;5z#s+Nu{XWKyGD}D}Y)^Pk|`|&^MtP-YPy&B)Z4(qpV zAI-l`C&Gr##^%D-hAvM3VY(WvzNw7;Eg51XL{9({@@#~a+E_qhYns=xX-3yp(l(+r zh-@m}VH-z7OR?V4ozq*!+1@$r9cjh?t zT)WMl+mUZ}fsdWf$p9 zs8)>)dFg}9h8Go8uqGN|CxcwS(cO4EIQsIoa;Kh6l5O}b1ueK;+p>E_%>lwX^?Xt9aO zI(f0G#xluHa$y1BHAySxY=}Nv9hKdTq(>zIjiQ1@gZ+KrDe5LC1!4M=jM6fvK>8GG zo_gbSz+17AY^gwyd>pZ{2rIFo_ z6YDlY)@tTZ>iEg@CtG}H+NIN(m87scg9dy5A+}OaFYAWoLg!`k%m=N5x;G}5(426A zrB5}G`Z-#?I?huwsKX^Dkq82@s-i5F)0nH9w`cwNm4|JqhfZ@76l(sjD=0n>=e60Z z!WfTnojR$c-!>{;h#@nWmH;ld@%o1emU)=u<_c!vz=lX9*P40^t-0t1)B4{9a)zWP z+NlwDtm7diq&p-96zfUO}9%vSqMDT)nlS;O4{j|D%i-kcH{ z*doAI|270)GGoZBI|ezfZB1<1A9l5@pd6PdvMJ81R)x<85#O}T7qR3jZk5dy8b=o~ zbeLa}m(+(E4rRD*!9bQU60q_i~fE=@!yB&0vFBOpzk zLMKSmok;-Dq&}oTo~By_C8X9=gdTEl_y*W~AiF$R@wu47(;=(1z=O4L<+1tb3$cO7 zhrbX3j$^`A=a#SzGdKnZP$hfqSmj5eZG#V>9VJRYH{If82wY9q6ebp#lC3qDS` zBs6ehUYSrU%+4u*I%W>^N|2;lLedg+g}l_t345g2BwtTDg6)$Rm_^UpkENvx&cc5#Vm(QmSPTqPI!(L{}`z`K0y{tRTajs({Rql^T8~PcExI{XKSV^P%(2# zT53&JHO8lJC#_Rv>9Jd6%T!m!Z_wWL$Vzq!qg>S_ve@F4Fo{6vNLOE${dZb9lrBd(R2{+Ox`Y=QZE*!mUNA4G78XVP1Qg!O!ezoO{pi zA933u&edP>FzbDmd#isi;=Su3QihLj>xjC7{v}lrVgjp82T#@-5$?sKG03)Kugu#Y z(|`DsOr2ii+IBo!o#nEyE>~Y}xLUD*Y6P)_Fw9i`$o^KgLr%&^fCo=`9V_uCmQu8L z(GS<}MTtxGgg+RupFbk9&0jHI>CNz2&&Welv0=ie2w3HscPeY6cocwp65cY)ES#Zl z{?7F&`JRK+*c-OK`(W`JD)mxJpD2|bF7(z$!Q>%1l=kvJ2E4mLrE&c40q^S@dHi39 zpWkfa|LXLTRsSe0DtybQYnw!D9qR)j!s1GTBlb~6@&eVQUj<8}%9umG!7U4=#6F1k zW$;^AXEB2%O#Hr3$1SG}phMH_nXJZj@7=4`PV&-TU%xL%1DHs}t)Xg)3kBe44~|)#=^$tlRc{J%SrheM@tD-e@s0B z^Xtu3sWQ%vTPw6M8V@D#xiE^NEG%6&6mZ3zFp{bOsmiEU+Uzi_!-Jfn+O-|!UClM= zzr@Q>xLC?FJGh4#h|QQDk>x9*&@q55Dn&dq8av95*r+NqvengL6_Zs}q601eysta` z++xi>gv&`*b=gWvO$>UgL<`Uip%G^0)LzOFCn1TS;g(M2DOwG?NPkmDXC;HNN4jgsDdkTZi4IuwVnXJ&(C!BAHPc?@TFV zMB$ig2o`G@S6~ky)Jo*8y{DAa>o3eg64M$mevmpH$_nDMZ7vWNV%Eawn3+#y8fCb-X13=uA8~NnzZrj&i_Jgbp%CWiZmVNRom5^u+uZYs znyYHe&^#`@n{?oc1k&sZQ(JPOHBJediqopLG?m0DPRt$W96SOSZNmsT$3`2xX?J?; zU_#UvU?IT~NffRE;x36%V>m}FAI=3?O(OAdHB=r3k1;>X1b+UA1fDvImjy4x zj+p2s2dhzZc5^8OH@>14?MmR5VZWe$I!R72aLpOqXh@p>;E^yvp-1q}@YS7~FAoSm zwu#6Qfg?~+u>+nR)C}e_P_&ivV^cRP=Hq`r`}qc}QGdRts$J-R?Unb9qI^5#nfx1f z-_Tmr{oBsxTO#(K-kHfMo64JN2qXNM#@NJt3Us7oNzzhLGDb+Avd9Yp`3^>OkSJIi zWQZ*cz=oKTrWt(CcT1zLWXwJn0Iq3a`hJp28GKJk(>HOK4zDVV(Xk*nX0I7dD>uK5 z`)uOR*XPw;psapZke!huh8V(ie_I_xr)1d(A7*P)4^DJ4=GjTBuC5u=0H4SUFY>Tr z2CX=gS*Fw9cWCxiqW8ucOk^aVHZ`o3v$qh}ZT#_tj zlTLURnoq&8h`%JS}S=3360&7G-5So!N2) z)tZzvo5TUn+IkI}wc^~t%8<{%(M8rTC@oH9Dl=o*7*ee^rLC#~f7etz*&#AZd#IXTb6Ial`-$eMsWh<4ccm50|E-%ongZ%!h(o?S) z^C60(xuv8SU#Cbf9?5AEywRZ8GL@%nf!gmRIRCgI9DHQnS?iCgufzoJIf~CyMer4< z!VfeT(n76|-5B{LvOz>!(r1ToLN@w28B585cu=xn*|r59*z>efD|zQYB6ZWEZzuy4 z#G=2eC7AhRjB}ELfi!{u8)x|&0?{0BF?z36iKaRts5Vp%(@w1Rfn#SfnPiQCTUqW5 z3ACJ)4PZD4r?D^)&zOk}oc>ko4Gu7$P!dsy4#Sv|6CnSZaCX*sh1(um0LWF?T4RXw zG=c+mQj>e32AyLqGvJnJ)y4*m+$(CykIcWLUF$nYABgx;62ZF(Q=lvnSisLw6%=1 zm9_(!T2x}NgmoNSp=sEviCv+oF)WYWtKf**D|41kq|rJL-+gYFZ|=~li8sfB5kHW^ zyTJFyTrSdjY4DR4e3L%rrD@lGfVz7v%%!tJlg5Myq5B+&Oj1!RA{xdvBh~Q)Oq>ul z8PPNarr#9m;7|CwWXjR=ZK5x$xLWGtOdO(51}I;i@zM$~mSGhCVD*#*(qPYX0@4>C zxrqzvg4dcCIgG}Fp?#|FTU&TQ=^O#bU%T< zX}lT^$;HudQi|Ii9S7fFY+>6+Wd0I}W^i7%eKpYa{LMgkMKWGiGJFD`v(z4In(t}((l}_f14tu(aKk%zsqMb3=j~@f0!ce?OZJF zTuuLNFO{rr?Tqss;DLdnX@E<0Y$Vzw$4IRub)#&}ZktFUM;9O0lwThG*wB|^140KX zJG_Xv&GV)-V*f_#G90I5{;`VqMK$uw-`Qxu02Y?+Jl)fEeJ^mrJ)`yVo-6nTa>FwT zbnHO+TWJ!~0RdJR=jzTXK8)PYCpOIcBkg#J1@ZdcnBq6O$)_f~5zsxJ{=t$jHlj(@ zeJVFLB6kz=0I5%3{D_~;+iiaES3}Cm1j;b0S$9%J+Dw#_maMIHr*@$trmfYl+suVWz}Vot^B>FeNA11AUsfo(Pw*>Z46#!pb=}{m&99He-yY zyHIt`mo?}oEgcEb0hd+*ShFRT3OV1cdAjZb4SK6}Oa*6F`>7%;>hD>z^ioQzR;CS4 z&^0y7hdk$s+CH$)TLv!9id(W%_I8Y55teNoeM>76#EwM8X;@%V#fxi%nsXCmjb&xZ ztXpUvF+LcZK`Ob~in`fuDcUN$;XTr8YCU1s@{l}>H-UMFZCt#2I=oW?K(royWt51| z!8KO}`!rt@oC8Y+X4@eP(P{ef8@;4`HI@=aKt#9SQ&;h(zB@zp2D(<@Xb%SkFH`Xb zMqe$DxHj)sK_J%f$1FOZxb(m%bf#Ke$T)6655_q>BBjr$F+eiTS_;uVJtgwQSc@v(x24T;r+mh+XS4xsLJ^apu> zkto!rf%wMU!cqa%y=8NTKD|s@1flD#l5wl;goaQs8QgGeH!x~0> z{13z<;po`$X5c8DDZ`Fl9paAR$8laju{diRVb2=zKJmlA9+p|cgmy%~GusZ6RCpK; zV5Z>M_k^aDTf)qGaqjW*YT;4Q_OxD3!+sNoUa~<3YG@!+B0*%j^uZ(nroz^{7FPw{ zmg;?9)@K2yrHezlG% zaNj6UWsXr>*+dm-l*aV?3%%8iu`?p+j`u#Kat_yxq9Jdh(FO4`E)xedpqX=B;h{~CL;9HF`qVd#W8{ z*_kC4D3$Y-b${waz@2KpIKFA&GE3+40lkL8ons6GI0KLk+48?)kP-bv7AY|H!{z@R z0ZQHo%x^(m|JI8}Dz$DHu%{`>h4#ZAogf0-w{ zev7@$CG4GS|JSw6G`b#UfC(%3y0&?VhYGWA zK+hX-Y>`8-= zs-%?Qk4k0i4O<<*gW%|T`146U%PB1(c}>^HDBhVbj$pMirm6Q(e8y@t0b(Q)F!5WD zXe=z>2othkHit=pf0MHQw&5B59ySG`fPg6f=Rz)K|1YbqXw^%n4OJxmm7fjhAzW9I zR0!1@P35Ge%poHA49s#OeY?kn(9m+Q;w>SCs`Y#cHdNRBh}!{#Obc9~lMldeig2AP z1CEJ{j~-^%-|6ZzIo@v7seivdLHguWQD4B^Re$8g^?7cZ-cu8vtf9TWq{|%VeBZ}t zG?nuUkVa0r815f2eeR1RP8;O|S7HUj0tz$5Y!V`opYL@CgJOdou%w&lg zr1C+GO)Cv+nx1G&IxSUg?uy3cm+D&KR`#8Dqh2~wD4E#HJ`z;ivMAJIO=NY6H(jX6 zGw59vTBOCAI?fmg_|18ESvP~&u9LgY*9_;|Y!YDXdTAiKa}TAwC>i#98uywuX}X{B z`12?0JU1*B?{Ryq+5ZfZYO`j3)d-DNLg{iL*UvUwWSlt}Y>;RMYzme9aE=7U*Jwbu z4ai3YTV&WWjnrYAU-FM(MYFM371IWgZ7^6=4mnDARP{*G%PbR|1bV` zLd4H}=(miJQ^|WGcQ)E43L+1eQT?I?mRIm<=}#nLewSZ$IW~kuccqhUVjLk*YrH1* zN>{c~`M=;io9qbGIz(uV<-ya=8)%qnN)eIqfp}u60xG~V#FPSat|=h$x;kZwLV|lS z`UEA?{DSjKDG`xzfA#*t+KWZ{;=&;JE6H2~D1g6oWtQMaI^wV8DeJ34bnkH|33}}^ zpV2**BVCp=f$~e~!>UUCX-C-ix&o4szb10bI^;1GBtqtpTALC;PT)_FUK1`!09;Tn z4)hWhwm8!?<90(#K`t73Wi;`U6v@;Ib0-Us)Dy&~;Sn?NQ9?5<*9vn+{1x)`_#OY= zNL?K?cd144q}~x!kC1Seh4Xi(I=DE~m%81>;aF-bQgQU_H`kw{QHEDKt0@9syPSEn zbzfV$r{CzeIb;~6>N|t)4bcytFjN9CIhoUE{(Cl1y?bzpg)Lde99;zV5enK(7CR-F ze>Y3TJ2Y6L5pUxc_gf}EUj+Z(V!(-LFyZ%&>N>tr-G4Aj`DS?kvw8Y<)&Af70yP~K zQZ=M6isuQS_#+Ys&Q4lb!vU0)cLrK0>%NQ72?niYaC=mifjUtXbBKy%O5Z!V$}Uw; zf7OXQ;YzY3?IXk+NiDZrYzk&DDW!+AE9Z{hYnSKrkNfLff6%swY%06`C9Kf6$bHAj zMooiTocB9AyP?spse(S-$SV5VVU|ox%NmOCHdt z7CUJy-e{5Oe!W>6BV?%)?4h5P%9>2s?sTG+Qf=8+ha}lqds#{qa&y(Q7G7PAIO5e3 zvzn4FSTqtR&XPmXT5=L`ZZPCZ+BEL7PIOP(^xPb^Q5^*t+95J1^_7)N{LYD18w$lV zOg77kv^r~Q8;i6$Vl0}=R!;jtXL$*b} z(D;zEzW5#YJh7q*g)518=);*T+XJ51m<~$AiB-j#U6(Jzno$#JV(KMfV*Ai!rd^KH15{sOtxkx)h>R1~r`k~W-X75gt_tbmyYxJp1J_Gqi zkHj;M9>f}x=uVLzJOoRpKB-n(8Pfev^ErkN#+ex{y6bZsw&o_W$G=7_G86u+FCeIQAi-~-I$1S)v0us2QuoSQ>)U*T| z%s{b5B+G$KNFCLt=oPc>b%M&>=lzu{E+id=NA!{j687>yh?_M%tPxPbLcuq<&9{1J<>HQuxsMb*qBmcEd^q}IW)Ih zDrlf6jX+4^gP}-33=)B=82AgqK^92QLD@qnhylqO#!>({-I4ft^!UEq%~gfPRV*o- zrvU!+9x9QpN!1}fqeaYnLJm!tASB76n2gPiLM5#aJyk?q6&UQ9*QnP^h8fB8b#smRrg35IiexO?n{b3AhK8zS5IYZgXN@{>K-9cK$ql3P=M%`+| zwp@=tL|a40iao+Fwk%z2iYH*bPWBR;ZzDA0Zz_gW?7Fh|H14Tosp@PgDEl{)W7BnSY5q2Z=t=$y1H-pt$n6`3F+2{FJO^ z@|wYa?ZD{~s9&7hNh3KS_YH^YDUg22AnGM1*-Ve^UzjOQ=M4~b?{gsjfg5uwo`~add!qm- zM{bzCdwCdo;U5eXWFMt0uvXRVIVz20mhUFK!+Fz>;GT+}ptjP9{xyh#>pgMgoP`&h z#TDgjv-EM{UwCdeUKv%hizrN}5!GKdkxI>+i!oh?gAH*0qwCGTUz^ZC?$Keo3i`=* z)5cFE(qZ4xPhL%Wb^j}0J7-Bavt|)pWTZ0Oc=flT9cU1W>wRb>F6LL~bWfdGUU`|3 zcu1f)y0=maW`5p2^)lu zt?0qH&ARVGN&V#{Curza`ay(Fx!SgIWDg_uekug&LSC7&nq(l0(9*D!g{RL~=%Gdh z>ZtN0vGgstG8fT^Y=t!TS$!~X6O6im8T(jr9(yJFh?HCazA`8zS#3yN^C%KPtR)J4 z0NRFl*lmLPV7S>b4rVYDj)|t0tnF)Fp~!+CHMV z`YKJ!R#X^FLl!WaR8q~$a!$~)oSoiRcG_jVg9nH=m0oD_M|h8o{saC6)7_oHsZCkC zXJHrFyza;8=4R$s$F=@`@A!RWn`m#$g~l8qSY|wqz|P-vO=5=R5c$nP9~d5iGZEz6 z@k?_a87F62a8Ouf?TY~vfz;TIc^55$Dl$jOnh73t*Q&FZK;r%ohme_Bm30=vjCKiw zwf2M~NYBt|)5_yCVNr+BkMM)?1X`>1j`!6DTUN@MkBGW1BJ($4yD>C@pD1=~$B!Ru z#N;J(BQPb{JPm+Kxb-X@@=0g%i9Oh8uk=XtL>ugR@>Zku%96T60cETH5^*p|g-Fdf zt;zP5DcS&9s)Dakw3wsC-<}*rcA4_@t$0w%$2#morDfmAdego;Rn&I$7;w}(w!dM1 zGMy)s$-Oewk(?E`RZSO6?GJ~}fQIfpotEuFb2`baZkB^*!Z|*6Ksf;#GUGxmxB}Ep zLT;k|{teDm+aC~JuuD^28*mHp4mjdz;J4zV65C3gMreJSdBiwc>!84HBW4ZV1}!@{ ziuEK=YqC{zstbj>fT}d=3&C#rG0DgZ*A$#?tLc_38>IRoVz1pmJ40yS4*jhtB!M_P zMe>t?a+Wl+GXTO4l?^*}$Lrnmtby`yol7JutC+e=FwK-c)8xECzZzTpdEREfi;EP` za>e{0NQw!Hu38MrSr?EIBL|An0>}5ucGp*zRT0wBfV#qNLq*bk)Ua#l4ujg#O2Ls) z9gxyJrG^bCL6NG_AT7O zr{aSt;I?x1X(2&zIZ4YI!QbclN_sDH#X%eft6ey$AcSL_W2ETJSx!A`!~oDrCHx>2 znbDADjYdfLl@rfj7wcA&=sE)D1EZ_zoLfRvKPvI1{ z@Ss!bdf%rbmB3o?pWe!6@@jOOTdNCDmAmTmdfOuIRX9+#7o=b@H>1 zSYxV{S2hiK={;$PJLt~}_uV=N^&F#Ui8 zlWsRRw8z8-G8eq%zfRn9-tJeP34u5i)f5LZV9+~2z)inc+R7cC?I4~TG{e$|KiN32 z=J_|Ct7E3(YI|ElQ`VZ_@b8Ikvi!^wg}0sF^IS!51jk7wI2} z7X`>_RSn0@TN@TxKVvV(;9vYbbJJ&3_@nVS!Up@+ixM*db`{|Lr#YmEBR-L*1+pL7 zH!S8F3=Z9Q9jWUt24+VNRbMC^E2ZLsA*VOOPi=>aXv%MY|{leS``ysKconlzsUF5|tTx z3H26*1&J4Q0*g9?m$pqhKXn2;#l4X8inq`W(pqF$ATS?}+ z+9x2~K{RHMf&>x%42mFiAhzc{n#}q9Ck&;r@Y4FK#8|Z}>ewq?YlU`|{IlZM{-167 zDZTlviZf_1WmH-)$HXtR(`nok{jw|D)9Hp5!+B|i?d`=$^eJYKYeI-_TL607Ls6jC zeo^Ol2DG@s{R98jU75!TJAkDNJ3zGpzol}LzGKUTRvnz7C3!qOUzK6RI?o7IFP?N} zkv;&L#~zbZX}SAY4{TTk_41K>k3c@^j6Rd0LuHQYY^|E!cft7x>(mN)hGAXJJke`2 zbzJTco6p!vom=Gr4?u%zQ&yzWWgCFtE^2V2IT&4GnBo!!`V7C4mr|U&%0SUM5YR$e zOZ#NWaY->-{Kw@4K1KX4I9r&&h4 zRR%<*{2-9GroUuBv-(bI*XEB{eM~E5QOnK)jl>x&_m3St99r3+F0NNH;)W9o_mFAu zYUD>a0sp8z#zS{S45UJI4}8PPT|Q44euSC5z(HJVgUJ`H2(Mp6dp>SZrLe#aE68Nw zL(Ch2#Z3m$@0t@yL$`WXZ$SC+l2DcGE(GGVM8V)>byRcHORPR@PcJ1RUYPL-7pF%r z=*QvGlHDTkhHv6!$`7aAgh+20V%N2jgrep@n)`Wn8wm)wg)Wi^stOam;__O(SO6{^}7s@DFD;O|lYCC}P+ zh&eTC4MO~=K_$pJ?lLY~YMPKgOvcFh)+I3qmvtyWx%gmAWtmZIP zz_+YFTOdGSzeaFoPH@)wFHmR`$hNsw_O{RLP?EUvmDq+S#z$^30v4 zD9AIe<^ zS57aTa?MP(asQoczdd+1i2B_=8@_2F|3Uivz3rE_`)?a@HEUm5_zyr57s*up7s5}+h z{Nqoolh4i;IkcrV3$HW7wI}0@=d|1ipRIAc*WC+8;bllUgt>=6Vvg*c~KE&68g|2uJ(`&ZAr3#p*E_Q zu&;LBMz|tuVmmmyJ#=u>U6P$uN=YiXn1qmW@`umXVtM*Ohhv6K6CdTSU`;Z+wQ64` zUIy|_c2O5de3iO7WlE}31#|VGj7hlZW0!J<5?u62&7Ap^bxGf@x@Ng{N!HRMO#UM| ztL~uA9CZb0x}zC+vO`E@MRNJ29~1ZD_7}j+c(uobS4r1Jr&>3=!}eGr^QSwc7-Btn zy==D7Pp6nfSH}j3^|937*DTkq5~Jr2zUIixne@W4f~AbOp8G9fZR2+c^W??4KXM!4 zs&$L--O&~!#GCoePcqZfX1c*cx&qM zI;_ooe+7Yfhz16XkiiM3F!dD*+x-}Ei^~L{5De)&c_uNyonp26uPtS#_Coo%5>OC^~IU^C;g-up50(-++A*0Cd=;VhFBOrU(wiw(b zGO|4iJFuIWV9Xl^PL~?c%inqiGZ=O;BUf^KC6D4g$lJGLjXpy)>c7_+hS=1C9<1f) zQe~=QLKEEwtq6CvAv3z78eMY*mf*tb4Nb z+h~w%pA0@iTgdA8*OVu#+*cgy_@|nE$4;a)yiY$Ncy^7W=SD}y8@y2pw-7t{!=vAz zz^s$k(WWT&@{wmrYXPL*%ezOzl#&`N-(a5JgXxDYBRWt{KAGffc;V?VREsg%`xp&3 zv;&akAMRIS&R0BfZ!YbaTEO4D3(7M7KqS*x#V3NOwKeZ-I6F52{DMoU&S}He7#K!h zpVCB$!8|O@<@~pML#|8n%3 zjbR&5MtpYtnEf?qr_^i@XY$KBttoGSHi6#gZD?%Po z&j#`)2i7K8`h5Oo@FoXY3k|9csIMi-JX;Xk!4Qd9by$n}8M)bql-ZcXKUupEA~ zYK1F6Vb+$>BeZOR_G^J}HwI1y3O!oDk?dLH&gldAG!h?ug}SDMwoB6xIe=MqWuC=k ziF(Y42wTBemT`X9Vvkay-JekiLFf@ZygN8SGvd?!{H5ccf4+Ni|Dp3k)`22c)6t4gc5mwhyMV- zLFzr{{;KbQ-uZnB%QuI7ffM$Tr}+Tky(QmTuRZnXEvfburFl;oeT~^}x;|U~_%+cc z>OV_(i|l9Bw%2OKwpoz+%Mxl|)C)AH)t>9~Q`aeyq5YHk6_M`(SooxSzS$%A`Q(YW z&EC(zuMo9O7HOppR;>f9morPmzuHGoe^B;`+T`+u_1|43c4)H0)xOc+&^P+~546_r z()!;E>&8D~`oF&IaVCvIFf>DXgR;anvx_ZHBv#-_85|(!gAwZ;((0P47iMmlc)sUH z`R?@#XHg2>a;3GGKj0VKN?3g_36CDKrZU8!;#04kdYt`suCwkp?EiXytOx?h_eFib zq=|8Z9&qo>{gu)L)Avt-Vt}OJR)_djZi4NYU3_TAsC%s(jnslPv)ptlvqF#5Yz9dt zN<#vT0!@R|O2@7+>x(9={zoV~s6kg1ch{xaYs;3txh_*i(}`vNEvChbh>jYbZ-Q%^ z){D@}GW!DhDc6*RIe6e%Jb1t?Sv#!DiK|McJ}oAj zw>~|V$=R5W_>!igZT52y^C83eG%M8)Ew}9k8ZqLe>09*v2ytc-N+kIcD-2Ombv@aP zOzUYID*lGf&5kVkc)-~f*xeF~9?x1?)CFJnBh`{MIj@3kVGX-^^_n=%puPm%-UrfqnJ?1$`CjwHO zl}oA1RrUqvF;|$FgUawbR($*bF*f0%I)IOg1;RmSm_ANJSOQrK8*+{1HzJh!FLMV&M{b)TTK}Bd z8QE9EAq^fbi-_fsbi`XLCxhfbwuAR3zz3r}2!zb60ADoZ_0`ljwfJW}p5`yS+=&GC z3CZJE3F_`Kd{&YLc+86R7RKW{Kgm*LQ4>p=By}-KqA7q6Z7U)FU7OUGxUy9*c)u$|uquHXcN0zC%<+;t4J}Jvu&8u6T)0cN|hGr}# ztcRg}A}hV8mH9S+HVfzC@Oufo8Aq4`+k8a7G|P>qN+g@0XREpB;a{FTQP{cGMTkv3 zZKCQ_g~(a0dU=qjT=%ZtBS{Nf%6XM~pB0%C68??oQL;b654Gcmt|_QhD%Ozx-Bj{q`p4DTVkDV)HNhQ~-Np_08yI zV<%N9P3Xts$JmTwB^X}&@8RG7NGuVJmgP*o+4gqdJ|Fb|^I-aa!c;{KZT@eL(yI!t z={J#01Y}G`bUZ(B*{IkM_+SYJLkHM4vLp{&NA^~86lNoo%#OpNyW+9No&TJ^-?tr&}5_1z;5Ef7KlALZXn?R6=o_G#zd*XN^AnqjFsm8)(~o9 zO{FEF%Bp+To2(QNCA@0$F$_?Wa0OBx9a19;;t#WWa0C~^h>#W{B3^80&+o0dQI}E1Ix#$Y4aFGvSnG6{cuiKeSdvXI`x}Elg0TESItYfe= zi;5rEOfrlyzc(Us!(drxNuPo{J7bFn+Xw8I@}w3U z$@#2q6-UDfvlKWo*2KJsN2iFTFw)q@)QU^uRdfj|{*aE^rh!?~A=Y*FT>N0UKR-BH z&dv+Z5NG0~wxHuCY=M_;ZN!*jW1M-7-wf$`PR7+GWpTuvQz?gC)dZ#>Nq4T8i76ZF zQ1m$Y!)UT)auUvQr6?+ke`57c1*WE~ zjaidvfm#%#DxLG5Ldiw1$pOSKSJyUCaT30M$ z8__J{tr8SrCDym;>9E>n%q6i;!M=)*#C%nJC(OEfJ9iF0-2*%vJXzu$MV$h=Zpq1g z=uqE9d>|F)knEd*%bz&r%Z5IC`WE5OyAm`1AEoeHM$mGxXorI=>M3#L>eNTFe3d7X zQIs~N{ghA)2R1kd*~u2c@#Tv&QsuZg3y8RY^dwOBvJ)qX&{psLWVkXi@%p24r_BvJ zk1h1;fr^L(8p9k?I>bIo{gHL4`s36DB~El?1k(jez!{_f=$wezx5%E*HHU&T>uKD) zM)z0rhcd^FihdABKHTs0P8u5tA&Vhbp_ir~@&r701m-b!Q4fb6pzeiTg${P}(|IzL z+Ct56!1U|&zcLnL!g0Ad7Kj}nqaX4STJv-8ECzw>3RGR;cg;2jw4&^9qZAZ7Wty6o zS)ugD-?H)EkxCw2o3?{H@y@4ez-KzDT3FzQZk;PnMugb?g(8>N-5~O1x!0qK@WoH5 zWF)7s-0<`cGH&pjJz`9jCXx@!V|i*OfP41v!{*@Y`4bmV!y4H~TI(fSLZ{y1HU)cudv~PP z$@fdMIU=h$5Wtga&yX0Ee!WW$RJv{cj7A#a#+jP+jq%4LG#1pE^vE%smM zz&2p->_Hc`L5B7ZBm6?BUAevkAdQ*zzPmd$PbhfDxQPi~m1Ot*73p@vI7iG9CJjP? zF0`l^_-b&{9Sa7YL77r|^NhiFguDC*v>lElHw}Mp+efgX2H3f2n2xCWtEh(`(7H`- z2_&|7)L!?!9hBc)S;dVBVe2@6pXtc2#kRWRnPJt$3vl zk+VjoilBWDx$+_4JsO)=(xHok_{6FpLzhY_r#ZOFD`LBJy z-<7t-SqEny^@fimq)ko1bZQ-)4Hz7Bz#t3CeyK9=g|fEFxWG##o@~~f#naliLtE=P zWD326U83_<`w8Fo=V5!tzvnNA;$SA2*daPv9kHR-04n(X>b^)~eO}x>bu87ml;h_Q ziH!3T6n&=A<{-0TJ$rWS!Hg3`ti_IVZNDMrP*LmAx}}?s9*!GDltHs5!Z zJZykaWwb799e?YYZ(RePzR~aA>XwZq_olhR=%mXFc7zI^peMgSHY1^|`+O1YABzU{ zA`k!(fLryk#cbn8%bfG67))ae0``+Le2$beTx;!FfPLquvfnz-Sg1LU{K$=Mjz9%* z$8g_%5AADtCH_WpkY4DK_4vv?z6d0t?H``}4c`?g2?0|Sr%mGPGWnFDM!8`d$F2z64+;9p)nQraS}cxI>U<;gTD48UrxYDgImwVXj&$hj z#0R!f$#=K}S@wj&!}1?|Ei)mTmA{Q#fTu%UK&NiUmEg~spEQ_fdXo!CR9;M~yUzu@Qa4(0U`9sr+zR_s(o!jP`Ji zPLQ|_j!||wq#sG(+#NU{7SN>42HY8EA*Dj1n^^}HzJODI6FQCnm?&VeW2N+&&Xg&A zEmqoJy zD1^wK;x-rcw(9PV~RkX#vo(5<~=>D-}otaaI>v(aX zP+=x(U?fmV+#tkcSfk=7io$)wywISTTdwXR0WHfq)`*plR2H`!j~Hx`Qff^w5$fKn z0D>pG%RQx9{g$V0dy2-!MCsrDhnd&jJMVtiAKT9ylwZ$-DnLw#I;?x-9^9xsu(clf z;QCX+>M!~fRRP!cH=qQ5qX6r!cT&bFzsZSQkG;|x9z?r z4+y^r!1d;hx4<(b!PjZ1pr;{9*EpZOS3Z>f$y)B~%}uaLoZ!Ds(h&Pl82?-*qNBZ%w z3*+KI<=`)DHqlhbErN$Q$FwuyTF6EZ**gOce`hJ|$p<5bV^5~sS6?m7Um=tFgK$HW ziih8hLu1k8c66@B*dkskWXrKc>|p?zDq^yc0~x&jm8P2N{Lc1nTUiZvUw30`V;xQq z4pI|Nu>nUp1ncvo*kOJV8LSuI?_MPWJm!U>#Z(}?#r!i z#D~o`sqW+Kpcyz7mP!ZfM(bC~?*k1SNGeEHwi~kAB=tQRU!w%^*`J-VvftbKBM6icI*jjmOunry%bCq{dOpW#h@5$c^sRs!H?>9Fc!X7)UW zE@sQf7D*z^-Re%}NtVWE760-pmus_V?luEgnL6 z%2o*=vjNoTHlZUbb_>nEJi(m20>P}eQIcTRIC5^UOtiH#=`>$}%;OQ!`&x8H(gYK^ zIew|qRFY(qxksqd5^vw`_}-rWg5JGwTpcl3n8Hss+gRHB^$<0 zLiZXj)a0^F^8}@L_`Ifr15VV&mFv zicCswVE#(OtJ}Iqg%-za9}J(b%{^y?L5B#$b8vJLgccaHE-q5V$mC>_@-X+|A9!4~ zqyk=~d1cw8+u*^=Bo{fKyO+7y(~_2vj=|KcB_`<~VddZ$!DflX$vl&p3XAGG;WO8` z()SkeHKRgRVXQGU4Jx)1P&7)mxb4(E==mmKBN4#tXsT_4CKsv)G;8|oZc60s=jrj| zC}F_vBvJ1`)LliCCS9ufdiNB`6Pi8jRLT|BOpXjZbUF{#pBI!<+&(=Z*f ztZ3lz&cswQ=$^?kHBGsESqd*-I*RLK9kM;VELuZ&_&V@u_k(hjX}~K=PADvy?&zWY zfFHE=o&>bQ$sU|C!3^1vBl0F)0Gtl_>Tu9Fz>UDI?&?!0JUbW7GX-x);&~!El3X`X zmYfR+lDvvk>eP7D^pI3{IwoS^6$(`nx-0n6L3IFqRjB`r-5%)`F(4tHh1^*f8e0sS4L8zl!Ev$I|+@MITZ-XeYF+V_#OJofzBrMCqavoQEy>r=>!|v?V=2|GtD?woJj>yuB z+!kS8^-}G%6xWX`LWQQXnEfWYXuh*uE~b^blg-b2h_d}ROZ{K3Ere*2gSo* zvN00qSLVkrk|~$*$$VO+tc6X>4}9eWbBZxuafNB-JBJ!{B~Ryw;lk`@Bb8a|9`{_iRL8Bf#4I z{wm|jJcs%e56J?WJDn?Fmal{tD=mc@2Mr^lcR-pCBO+xogwo|}1NHnA-Q^}iV#AT` z7e5e>llRaHPL-4rzwx9BiZldz5l7XmLlpr0HQ7Cxi7P}J0DF^1NWu@CbcE@EW06AY zMSlfT`w=+4=R{nl3CRj}Yt!l=5V>jmdsCe6qc`HrI2=xuvM)1<7kraV|A^>0G6_Zl zb`71Ug4(--IMY107^zWIP}1Cm-YQsKD1k7jO7e#=gK*dKely&H^&%ry*am#<5ky5O zQRN>jj|vdzxP-SiDl{PPvm1fY;7npjyZRT(l|^O^i{T7ivHbb|bGRuOtw!Uxsa!A< zM3GR&k($$N3~^XF@iTsMhGA_ZgI6fBXDp9bR;ZewICDv_zQ9A)xCgZED2r48I>bKk zTZ8RHMU1FAP#BhdehkCy3Dcp9h6k1pRP|C=KF}DfI2*MX7mT=V05>!h!N;MTn_32W zlPH)BLGVaE5Q2(k?k{aFks1%>GW5JHZKva87nOMfh@(d}G!M5UmWAYrsCVyXO9&N? z49-hgwnDc_2d5;5m+xIh@~`l!7spX(ya4GFf|uMA4$;KE&GCXm9R}{}c~Gpfbh$$LQt(sO7@J0@tyn!~ zyUJllaf^wU$bJCk@?N`+Lv<(Uojk8C@}#vy#DS!Wt^}|jazaD;9Z6@wAP*-FBi~KaWyg1Mpse;0wRDT4){b+65 zG_5#9Db5A=2Ph%8${|1S&@`-QA-C$q`zQ}`Mv!!elDwC-ooZS~H)N1U!6cOe9p7Nc zlk}n77?lt0X;E0D7~;=(!G}$#wo0sPS++I~%*nr9?wgnwZ%xZ6PY6b2e>^qp>foc_ zZlIUDsvdIOYv~#ARn`FU^Z0d=L`uaEVSuHEJ9HMlthwE~#_V4^Uoy7zBE444(#$P?eHQKL6TP)iIobqB3N*x8g~=7Ulk zXv^l6rUm4HJon`>UFsZfn6fvIt54Q#^s9DH@5na2@A^T;S@Di?7Y6bPH9_tX1FV+H zqExWOTD=go_}!r@(v`($bmZ2h8fQowIpfzd4Por+b=%8J)>O(v5n*ms_6$A5g2VjM zGpCpBT@3U7AZ2wVRa|y`>IPFgPY~9P{Q<^=AjU;cSTT=Rvlyodmb8=*Brn6_Gt<2$ z9%13w$5}0}t$%&$icr!Yl5F1&i(+|dOW&o9#-k?}XF(XSbdOApH-o(bc7G!( zDqU;du$-$|T)e6aZyObwWJQt$tQq%@u{!2p!JDi4GPn$K8*LA0gN}$+Ut2D|t$(^g z7f%&qz{Q5&+Db-&BVcJD4JXH7DP&yx%Aj^Sw1v|*n%_R6_23er+6UuxSte1qwV`^B z*Q07#^t!*}-Je-nAq^Q;F8t)jllJ?P*>hBn^B#a9v zb%Uz~DKwqytw|a|irSZzs4m-iKhY;Dd?(<0#=E<$g~;-9h}2KRU4j_HUfNZ6T0*K&tL$D~7xGgLFY+91yYXch3es_w#fSP6HtG zAqfL7UzjfXK^@oyU{>~w>o8GMDm!;vZu~qXHc=7vR?PQ!NuFlsRaOL z*#g!hzl|OmUPP|5rU=-oZAtL?BEq&cH#^!+fxG)kDz?eoYAbX>DZp6nN3-}{R zeEmx**`%^Hx=kOgBRenn_<`~pM>NqhzWz74&p+Jd4VL}Z>hEcH9q7Ayv@WTuUA%X95GLOA!ta^aLiaXS|s6#;o0>85}5Ti62>Z0>y zgh1XX?%R>mU;u&;x8d$Rwy%InPGOqB)<&5^tLGyYl2EYMQOac+&`ijB~g^-2g$iHLmM2MJyb?aCc$g*8JMy}*dXbG$K zg(o0)(7u&UvPZ!5m@LRjN%Q;tG_5rLu}9qe+0#reA~b3zPwmf}&OPs2*PCP4e?J`{ z`xtb?je#gpR)6<%X*(uNQFDmegnI6YbC6!dP>g1oJ;QaHuXPPNGfLjdfKVgI?JZ$V zJ5E|Nk19nCDaz-8kVo7zM>+S2q0mrpo6x|>33b_=qA&e_guP>sWbL{pT<)^bW!tuG z8(qq>?JnE4ZQHhO+wMZw)Sfx>&Dr~lIB!I*i2RuuvDUTj`?;hBrz>FEV-THE93@>| zJXR#>uGTzWtkoo44@imDc=lCPe1-{KLkZ`j$Y=&qoTCBE)^36c;a71fPg@97#50bG zz?ZgL;G-f=y2e04;ugt(D1DY!!%oV?P#)Lv6wk>N?@&yvhgy|ib|esb3N?WprUg?^5|*r(|)<$CXV{n}bU^{0rYex4g5ww-dVxtz^+-s!fU$k$vQ1|+E1 ztrF9iZ=KAoGse*AX+J8#SmJdI;@)M{r=JXx(7KX*C0;!IEQxcVY9Deng~enx zNi)+GCwXGNjVHS}C?ecYd9vp+Z_QV^f-;e>zKwbf1gm5OwnnIYoGjH6W#k;GlsW}N zO)d)K#M%=Wa4JPM!FQO5!UiKbCqGlwBsqfszudJ}l!=(F(;QT@La7Vu;aYR5V?2iu zWg|t3*;PbR?WF4;v_ax@X{oK7CDtGKcA^^?1uqt7&m4*3?9B?e$_dz{5kH!Vxraxm zhZ?F4Vz&xl>7-ScML29~b0T5b6NXC@We)(@3d5%m)C+v0N&SPPC~cwye$lgU3{eF& zk0uwTHqPLs&at3N4_N2?%upF`b_8TML+Tl7Wh=csO5s-MR8et3m8Sky5JWh)QRF&1 zCLJ~|UjSJ?_I?_VcL7Z?su$#@w%KVQ$x!p4@`D7SL4Jd-<;sjBIf~TQ=~;N{$Yccd zOA=?3-!@OjFtbWIMv4V-gsg|EgOWZw$06F`@a*6WE(Z=l?8h6d!>Fi5u(SiR=70@T z8}uMUt<4gvR&uIHq!jiYu1w4lcM=6e6UhLORldW-mzC07cn%UZf5{&u@73TsG4xSt zIKZ4k&g0J#0=SQnv=xU;$F2qAsfx??xyn;X;T(r_cvIBt2C7DXai2v{ZU&8Pu9NxZ?0F6s$sF^8DDKBojxlQKaGwQG(V|&MNCa^X!YILwiPmE7Cw1Kb>7wYTDn({q0g+GftR-BqS8k=mkTHpAu35Lt{WD*p;G#WJFXj zh|jWuAnUl8CIM6FjPS=$S@fr(FH(IYI4Xi>r%G0H@0-Zb`inbJGXvWoy{eDrw#w%% zC+GTm>+>n?Is7MT9lbx=>aQs6+gLM%2se`cD`2D_qCbg(4-p3P zNkvoZagk_A4OxWL)qaNbbKvxOUDo*1UZjRLhRT3FjY?&T53!J^6Q@%@ALPrb?1fs9 zS=ynF93Iv&;2|79!4YoY*t62yOdl#;8KoH|TVr2^L_!T3B^ z4#!R3AQH9*qk(A?&_8tnQ#*wtl-icFzdq53 zuG*JwN^fY5)lSyHI6XiGm*N9hr`7%Do> zzco!Ga2DZePQ=L#Rs#OP^T-{AlP0VcgBda+nOuJ9s zkyA*B-GY!XLyMDA=OTA(SE2gYhIqUbIBpeHsII<7;f~Z5U{;bTOy8@eRV~Q6yr*{U zbi>B~+2V*MZ|Nn!VXivdM24Ov1dvpBE%09<)~L~;y{&$)7U>88Vm)%Ix^cp|8dQoA z#gHe|nZMvIEnLBJqNtJG{_L%|_C&MBZDKn5lH2)G+^*hT*Er;Friv+F?N`8C3Q~Ys zY@+okttu78m}xGHb#72_{7n~!oRlH?bH9@gcH^!7<_62vgHzT+VZdUb9D z+JUOU;7yI#&Udm5SZ$(;E@lZkDDrH|3r+78^D-}1Y@&7Tg+WkfPCra@C#7p5$LmSW05R54# ze48-zHN(?Rm!i4Q@2WHjM%5v&lyO2q^baC0kBkW}L3hBQDZ@O&55h4s6QpT3UuHa1 zs%s1jy5v}CYmtV~qw8Dy?Fd=EX_q0{S`+t4ZhW9pm5`8#;sT=7=xKc}8mJi_I%{6FS!OcqbnH3rOK zT(}S5B0Z_Wf7~P|KYZVYxj)0IpRg95(ekY)z3-gN=;z-^(Z5Kf-O3@?mns)I7>jag z)8MaUB+WKzfUPAZ&2Hx3c!fN3X8BTqwJH#UHd{r_ZAKWa6LE2zr;uKV9(6S`xrjwbV!3W zUXnh<*1zdJ5K#m*QM@RMDphfY`G&A%|JL0D-@Igq8vYK*n6N{C@=qw#qLVPrk}Kn1 z8|x|knljzb$(Iugh*i84>p9;H7FQg9%}YSZ-L?!@*>1IW?RKJPB4E ztORtwJ}uu3nP%1Po)d3_JI7UseWYA=!5nL6l(P0(pAeuzWW=}b@fwMh)TxeUN`#-XEq2ywFeb~gl zotgOBfS)#tWHlQmscPqgVlGgPP#=TJt|Yz2JNzm`qph+SDVd7*P|NqlcGJq=l75m( zk|*Vwzl>LEI8a9nj>tM;5pJNDXr$&+iY?_m+uTf;gLQ7#Yb(%lKZ=e{=#JD>dGt3l z@5BhXdd^oHK$d;j+Jd+~R` z)~*3p>?eJyR$8g!T;yp}pw@T@ z!naAEw-k3BgPV>p-*rkz&pUl9hdH)xziHnVGX`QaN>_Djf~(PWO-A&QN)N8WbRI=1 z|KrLlx@WWNw7Ft|wLF*nx#tgqW2Pmy<@bIqmS55x%ve9g*v%oOETx! zh_8ojc~prAZ%OatH(nc3%N^nfWy#Pir(4%Ng8H!*#tXXvikknhD2GuRK?jl{;Zkr` z8Zaa=0ya-#)8sA@2O$APAPYo!MgZ472NKqG-~^%(`NzLEQxtXwc8KVLLD-VS_D5DB ze0u-U1pKK1`z9#d9St{W2nBS_lpnr1EPu1u*2Z292p{OHC3pYGEC9ntrFTcbiTi~H z9aFm`d({u(Xhwm298z(*FQ)AdulsUu0wjl*tp6=~u5~mKol4BGM}eX9KD0l&;Vl%T zXFl8As-NFIEC61{@5{+MUW`XlUP-5SIk50hjq?h`xwhiy}*&Tocx7+Uv}^sKJuC-$r4xYEM(^c#f`#+lR5XWX~@R%T;^tQ zYp19;kFz|4jgcZ(?iA8PO|b^2Ni%RMY(6?8yc9+cObf;o^>n*5>%JkOXf0v78n!*A z_ny{Df*Gn-9-x$$-lI=49X%8sy_aKJ!q!K}XT7)5p-gXI!LM2I;vM3LV0P09|H)gm z){?9m`PhBs*BrvBlimBEn338Mqtxl}KU^o~^-&`uv?70yCA%#~4?4-mdHamKs5cwR z?pcw&K~HTJ?_5v+zVNXf;APl%j#X1(Flu6>G*5UF`jq?)TE)83E%D>$eUvM?#P>4$ z>q_RAk~SCbbcQ+WW96TWO#i14h5rfv-v_<`lHn6oFKvIw0m%p&&xS*aU1r$+rdi6?lh`KTr{p3P;r66HPaNNLiQ9LR4nH#cJpAa%2Va_R zH82aW>@aV#q?{?-aGOL0qrL2N%wI4U^thC@9 zG9I99D%27YdCcD|KI4P2GD{us5;TzREy4v8p=;&Rj+dOe=m7bcZX#2uR+#t=b!LiB zuLp4p?g9E5Kcr4$j808MbZR&^AOxL@4+Y#(p)PNk9-q=wm`0C*x+T@6M;fgX0PXsT z<3kbF*iC9_LD!EKrJ*vKCjnG3TBiV_A)H-M^&{5-0=pHzm#kC?udDLTFb&Wyy_H^> zWQOKAF2$K+dN{2d2B2M2iUus%qk1k766JHsw3@pqLh2(LuX>(U6YylSx;+Qn2#zbEc&ixyMF`iq1ftMr2>lEm&(? zk3ToGx4$vJ^mvo(T0BlZ+wxKq^bpf{qJDzAD@$H*o`a;%e#`~VJI%@LwCQNWoVMA4 z=rDzNrp$@bH_6?O{P62YJhWclDpAdClH(HitSMaF<&F2z5=?s9HR_bt>SYvSzn&cj z;-%}Q(5$!aLgn*)A?auM6S)exfinRMj%?T|}6Tf=?;)ct8oneb=_^00%X&`x{0-elqbjEu^t4LbQEI4|Rx6WtS z!{}O6KdQeJLOx6&P&veHVm6-#+38w=DJPx<;G{)jM0f?qng*}^+6?qgA){buKMy;4 z**P==?U=#^WrUZg=2JIwnaa7qjI0d;$vxjb>%7Ac(}R6FUx4J?&5x){sD~^9IZLB) zqo4Y%yN}IhkbOkUx;7|JN%QAv&%eXmaccE_+jl~r?LYT@ z$ru;{{;w)s)%suaq0e{Umu9k%5ma(+6fK(psH}I{yigf%o~*1g8kqUT1lgKoit70S${bd+L6kq zb?1c*w)5uBOEy@~kz1PWkPybNx+Sz$4d*VkZ)c$GTC<{IoXtQ3m(SSgTT!_pyESq+ z8Wj!VRjZS*3fO*-l$~KlbT7+Q_DsxIb)!rV84QPdDt{SR(L26=xgC?}ylcy5_DXE* zco@lD@!B0ej7Yn)-@^>yvPbe33oitohVBFg1-e{CyBOOw!|anW#J<385j|w7V0#97 zN2L@@%`G_i3#(V8G?q#1(yb)ol=*970j=I~o~0Yw37VDVD=av0dLr(nQbu${`D*hT z(`Eh2d6VqO&TF&ak~ZBFp*81^U~5)Kwuoal2MwVT_^w_QxEv$F0X)1|Pj(eJ1Vx2g zi2+qF!r1qoImA{w=tG;DEu>U$V8e~AleIAQ2}^8MypbEOL-lyEN$7IPS*xbjs)T|u z=JkekFvgxUOcz&Ux9gRhRJh;n*%nG0!`+(p>4zwJQF0?r=^zp0QR|dO1H?a}fBCdA zB97*8F&`9Vb1{{qKh#VEi9kRnmXe zf7$3k2BH}S5`ZjycUvJARH;&-@1U(CmT3rBR7ltNpU3ZBLqvGL6gAN=r}#Lm%a!~( zm*GE?ffLR;dsOCsRBzmQqqdk?vr3MI%p0(~*>Zg0Ir)AGo>=|;_)e(@x*TM8{@GWG zpTT%MV9vk!vtocO^5GUeW9Ig@IR|g2Y(z8jK(KlQOo^w^TfyyyCxiUctQXa@yt93G zMAYn(Z>VE|&-lY^_~#A4opr!-`CN(D>F0;pTkL~@TCP|EIqDQ5BnjPUg9DFgxfV|z zmPw7kRxMXr+*D>Y=n(D$K#|ZWiM~y}>X_pR%yUNsW%i~$o&rEDoCXTvdl^6!?R3r&5? z)^?N*x2FDgXUHwvv)id6c5P1`79u@kmZlbt@Uj zMwL!`iV_R+pqn-B3M{I)=xT{{%$VDVL~ONiMSP8>0N);gm(+2nMHM~SjkT4K3FPe| zc&H7;;z_;9x`1}N8T))mH#}{UNi@Cn=>a(?_1kQO8|had11S7`Vtl^jTc~QO*5C_} zjEXbLJcM`B&E67ZKH;9gs?$U}l$`h5pg{Vy4>TJn7W#s`z?HbzTUHzC)&V_NQrJB_ z1l!okuYwANCAArBzh;0QS5lXmb9RA|F!@Y$=1-3PuBh|mc^NiXQF2%2v;`Kq^!Pvy zMtea?G%WFf`TpWV3G?tu<^D1kqulP=Lfa&kNc|$!UUpJ!$s^qbi>U)0(Pd$y){1!G zE@3!BOqYY8VRn*>WCcE|Od&z~AcuQ?1)GAJKnF^4#}%gpN6{k=5{tt$Oj2PU!x<~I z33X)kBHVIE=cKxGHAcC#p0Msd--y4Z&;+;sPm6+IiM5T%qhdwEMi{(s-%=MrM@M74 z>QR(d`I&)-pWm@Dn{JWm;>nJI!vs7m&vUImEaxH+pNTC7;<($93exggHfD{$uJYZ5 z3!U-0&sRfsNiTs6*bi!haH(E5Ry)Iue&jhOX1OGyirO!1BAZ)hh+97~j3@{jEGwqM zao7Z{=>XaFH?A7EJrPyuH2Oewm>v7tM*u;7VYuOQ?Xo7@*NULjz-hGlri?XbfM5vt z6{cPZm_Q{xytGF+@m{F%&pF*C)!kIfwFfRCzf$d~@;TL2^n++Be?=+r7uc1{# zwXG@X7+Oddm&U^u|Nbo<88u}~j&w0<%}ytC%|H2#_r4p6z2CX)Goa7tbeDM}zGGA_ zM7oMfLsV7`DaVgiZ!+6*%EKq>lDDPy1D& z(FP;k|CC0av=n~1F8=B+$@uUqKNUYYZkhWFYLL}EOuaO^apcSbyTz9;GpUW8Vfi9VvkB&`1{KO*gOoPpLBkjh&uMA-*1O zXZ!O+v-QZml)}@J)~Kw<^&yKfa&d~H;na2une%;&5Xpj zHAD=Kl#P@+-7XQp1W#2d%;Wro!X%~`e?>%p0+jw529F%C-2+pMw@1>ZAtN0`Aa4o$ z3mTd1U=k;mJa2s5%?D&dtx@Hq_A2vk#BCq7hs=7+He=bqK%F2 z1qAMi9DH`qwc7X~2~p+|&pisl;zY%X`?Rv#$N!x(dK|m$8^9^d3P~eZBdX9iFtiRD z#3B2`l!Y!qKet|V+54Tzum{*vjy~99`-lnJ0ooamcZlDQAqr#+XNs1SF^Fw+AO%7G znV(cZZS$yoc$L?r9d<=vXZAWlB92sis|dX#n$s<4PcGED=bln1L=tDVD(i%x_Xf-> zRcZU9Pna2im@9)cz9^Q~&PdJlq;9Cf{M4G}mXeR#VgY8(ZmOjZ^fCV3qpKo|h&W!< zKK)ve#VMQfsI}8p$wsOvCLw84Kw6fFR1IuhqUZSIvsIS1O_;V#dnLM=YLt!9HrN5e zG(#YQMQ9;I$P?{E=foXDD^XE2UY=_7P|TQ(lY1}-+1{W6Ub8WrhU(|2gxa8E_Kooh4}^zn6jm>ab&NsL+U zS#N%Rr0T7b+B=#&iGS`Yk1SKa^wHRZ3W&IKwyx#Qk3Zjqm#p}2u-=DU+qm;XsJi{& z8UAH_>PX{l&&PkzEl;~QE$!d#IiPPH!9UO~|1E?<*;;-<0oCVv*}0k;HaNfj>?cvA z9HqbieX{QySQgl~;-7!j8ZI%i$z@37cLF{OlElaEccL}sOj`vY{_Z~S#QJ++cAxHg z|2#RN2a2gJ%=>YK>cpe}5W67BMpmMXg_~x=T%gD`b<9{IAD=2~C?`klM5Fu52(g+rg0ax8xEv}q2k99D@n}UU0)a0^U zn*lPW%dL?FJuHQyz7T8mX^Ba%TO{7W zVcj0$Gv#wuyN^1Nc1XzuVW%sO|K@DG2CE+`t0zv+B+0XM2V1~(yhd|t8$kh$N~f9B zdkap^W?3yxBSx1(6H6wGZ8HIdlaicixaH!=zG_)<5m_`ZKsi5fp7#SYq#v0=NhAAF z^NbZzP4*cAK#y1eIr@_vQS1_uk?rnACEOs^DjCbqyq-)cm1q`ovoL(yW`K5+Y$jHi z@DRdzc=QFc4Ta*wXqrec70bYcft>NjhBqOZIA=Z$i3gv^4xzdIcdakoZ~wtRw+{+X ze6qLRPR_9Wn>LZV@4{};*RvxTtr0>Tqlp26#6AL_=zbOTt@CvOB8>qCr~}6Vv4B1b zd_h`#V#%E*1ZlBt4zY3{*eV&px5Nj6KA@V>?qX*Z$Xhsj&6{1_P&bUjsd@a&#Hhf| z8-qreo7ENO&X)H3Zv3q+2RGO9xPq?i`2}O=5RYxw%|t9kr6b~lJ|o?*!5QQ-7gDC} zEQt>qq!5qi8NztDu*7`whvey7hy|s@xG#iS^}mNmyW$`(-00cS0t~LXJGw*(;-!L|1}!;Bzuu#Lqo}iBf_mgectsihc0!5E;h!!UasRlQ+6reo8c%Rm)OyJ?z!d=Cbl9lFhoUNR=zyf+z+ z*(Y8+H`n}MfA27SwHb(0M}$z#c|vpX5!S{Z?#&aMb3_$;zmpIDx`tH&n(^wMIO&Th z)NWI&RGXKDUWvl>cy<%Wt*S!qNcnrh_b9W2Zk-`_Btp;8rfMH$b(u*?pf}FD(<{ov zSk>!gwo2usAz3D#g30!@@@&)`JDzTyv}C91j2f)Y;iya4s&vA*ZJ*_|xK{OOsy zsrr7`=;h5ygKy1-dv;)_x8>U`vY3>oEUlMYoOimye=a9)Co*`UD=KaQ@P3ocympIa zffVup(#AH(S*K#{f?U38M2(FReFIgF6Tc2rr^Y?C=2I|l78BhboLeT+rtJ*wsnZB+y*{fWrELByt zl(s4hFsRTgzexi`RgAe-aw&XItB9*B8SSKmo+gr_>7P{G%d#D{-cT6u1c3E5np2u6 zNOGTqPhkasmA=fdb}LnZl{RswvGL)p93&bhzL8e&@QAIxz%W@k6U1F{B(2PNYVQ=H z6Q=U&agdw~gJiimy}ONkjVg<>7@Vu|Wxu{3wrA6NWF(gni}B`A3vzXKfkr#8soNx5 zRemdZKnX|HqN~Qz-~G#do?i(!Zk@bWYf32+*5Ib4_DySxG9b<2iFO%6DQwM6^`yn~ z(*0?_Nm0c)g-@X5`c=sLeusRP9Km(VEb2AQ%|?a?hDE=Yz?!YA z)hqc5(5eaB8PC`{CUft-| zv4%4W87)QzXytQ6M^b|Zj6gaCXNkw^185*u3AuZNqPT0Vq7s%!AyGs06FNU1W!#_= z!_fW7X`uG%4r^%^$j{>Rl`bVxDEF91ambqM7k}sMcJA4!o#9V2UYRF31W>p`H6ill z$tjKq{1Wf5jhPEj#kxu_nQfHLaXDM?PlPGL2oX+4$pTM$1&KSM6I8(AdxB-(g-_X* zz5aQ*N0wv-qe$u*2&r9jV$mW=>?=Djo%F1o%}Kt+lOPnIIYrxffjG$lCO90Or7t#g zhG%f?S?f=yhIkWKiFx5I<5J49tapZhOP%Eqki*$RFH@SB(fmmss~%qeGg zZT&q?!6%>P_j6?7P9K~?8Gh(v{^6$u$@i`wQXwHvM=r{e0=<@UTAcmdDKh#SsOP4( z3aSTjyC$2gP$yZ>zNO9VExeU|!$v56L>BxN-ps~$einX1%VF1Ca^8B(8n{p4LIo8i z`fu1a`G}XYmPGTcDRBr&3Ibw%-n*7W6Z^+(!hI=si(-1K_sY#aN{H$5oB&D1M>Msr zhGj}0OrZUtUqq`N5_C3--HXWN=YNLz?XuZU27iNH**8H*_dg3OhDvj}0PV81bvX_?lh<)#mezy96lT5L2< zv?=mDue&$5>ZP9Y!6bo^D$gsS%xN9 z5|{}$MWy;p3BedJiKcn^ia=A3E@U8iQ(<=bP;wrg0)UP|HT0V}lRtgmf~jVVhc^JIf4+`IaKcZ?v%JLLuzZ2}(?SWKxuL@?;GN|-HH%S0G>RljzXScB`U&c;xM4U`kN zWc^?~(IHjs=st0fcwUZBw34~dzh8Ut|O zb&X|+u+A0o!w@#(-*J1WHY&l<{;;5;`N5|J@5tRr0^#_5`$tBYY~#pm04oFS{^&?u zo}@e29Vi`Men4Ve1bRj9E@u7$fY>r&u`vGvgttV34wb#NyeqAY)Fvfso)Z|SOx%w^ z^}%~c1&%7ek2&YQmZ;TN2pk|Ri^(ZIRg)-H9_NU)r$LKPf8%lYW?e3vL<43{k1_g_ z)k<5qsEBoftW7`c(Tc29^H&%DQlCK$rwrBJX;>ATUEO(?ol7#fF$k-kI4Y;pW@y?)w-JdFdor1T8DUCcd zNEh3}3uDb>yTsZCGF;7E<@eRJd_#!jmR78LT3O`0%U03OFPD9;^=sy@W0jGZBUZmu z^Gur8SSLyhxES{>CEDTRqlIJ7e(iphnXKM0oM17$Tcqw3?KrEtPY-QkMf3#n`}hj* zsQIbH&MG|BybW+33YFjckbJYyQ&F(rxeH{tSdAG}Fp2y&&24q1idf56x&Pw||T?=~IqjEm9#!UE$u z;~7uZeV+aPf8*P~96Kx#hhz?w*XA`N9e^`@z&!9b>AbKsG))bB0UY5XD)e zalz+^2d>khi^t`ohzrcHt4!+7In^rK3JI3a@$gckK>z`C6KWIpYG{E?Ub2FRE**mI zD1Zupn#gLjy*^B#%T}#ru+g0^7x6aAglcZehFpW&>fh;l>w?ipo2@!7y*azC{1~NX zo&`oL!x%GCGHBQJ#InRvwW>o;tA-+dG3qWI=HI;B=Miv<4P#b-+&%`@hI6r;#D z2@JKcr{YOs!*LK~10fQfi58u)gQJC!i#yHAJ|SkN+FbUL(GI_38mOC zWu&P;^?HXKQPpA}Hv5y6TCpN=B+cmULkNFvu9h8%SOcvE?9!c|&=)tM*6L^!8VW=f zndNNy&Jh%F5y3n78u}8;L70(u?kBr8fKFC+0xJbt=m>nKBfv$DzMF7Ndd4Rz{;5g( z9JlzuTNs?NUR-<~@P+>KR|#!oI+`{gpLXYdt^WLv)StAD_4>TxRvy>vg=G_a*X0fy z+>bep(#Yj-R#YgpreG+x<-Ve0DyXir(LOXF%YEbDr*OR;q!u`=8WLgxuLH9;X;C<2mElV#xa$r77VSboUN(Z+{3SujFf_x zO3~~J5;PPfVnMG3?ied1%XozLD$nvVJm*GAIX8Prc*Sl?zlj;2&SOFwWUKL};byKg zfU~W76N*^>@F!om{kpFlqa=fQyGe!L+p}BSA@;+E*o_C)iT62S2ipuGIw|=5ADGg1 z|F$^$&77Wpt7`uNQ{)XTzAIV&4O5cTF4R#0Kfk(aFE0UzS^~j|lqf*60sR& zt~lw2-RaT+EHtT$4=Yz^UlY^oqtnIISgYE2c>|A>ot?#|G&udRXk7)SG)?$KXSGa( z1Ts-?T`V!D&XG!CTcV)d-lAC2swB-YS<`Yb)u)gEIwc7T{SuUKrG^%rt_Zx#g<_*| zU#?Vnn&oAuhjHXMrou^@0W6|Axl}l=a!#zoh?xpie*QCgcG~Vf9ux2@8Ak*V%ZQJgihWfL=A#6QLOyAQD_pOq) z3_(RWG3nJI+O3~lvz$xUL&l2m{*}gPbu@!Ayufe#TqK`5Eo`-R$N|+&RclHsAu)5a zwfC4Qth=+gM0HwWsWN$CG~!tmR05e-Tr;-b;(=AVPNB{Oe7REG$F;;MMPMU82(vYHp$3p>=hbg>=h|*95_c-YaZk@-s;~PDQ};o!aDb0equEhnW~1PXN*?OVH?Hyn8F{*rh&qE>GBiE z@r1gPH#^3fESgw{ruYfPsrcZe$qTNB9-VQYrBY7y)*^^|nT}5_b<)}l<&r(q zM03_`$qfrV(hOB*;{sxx?cYbVZHsn)X|8C=t>@~=?L+KkvE}FiMy{!p{CI+R|%B@%kptL<^g5=%{X1p>bJk2s9L2-R;1DN$Rp(>WQO& za+#Zy;?gY|%$MtjNgROiAdGlGsRp7AGGbd65Z@Tyonu~-u!wCP<-;f7S*nR+WuPlO z*{vSjB3DK#VmGfTQuL~I)OMcdqlwGhKulTXZm>ZH67}@HlY{VV1;3C>@S|6{S%)c$ zLP55j%DLneG@RV|N4SNUAWU^#y-?Qd(;YZ-o-)Zt+|H33BKi3Bof3h7w9E=bJWqq2_4 z+SwK&^3aufMDO2CNCuI7o(tErWq;7@H~6$G^v1(py?bZb5}pbJUsO`?5>n(*@~e9u zP3{Z z8~mc{zelg_|2(_m~FR6TUqLYOG`XeupN1=qqC+f?n|N3OlVJEy!4?lUX2 z$HP9UGpE7wNG$nLbi~OOGc`Ah{_cVoC5`G};ReU2Lw>*6Yx1VWdO-H)4KA%yRb;bT zh(=e$f~-0QQBS0wjL!Q)XN0be<-#h4Ccn&|pq4t;d_?fFp z#?9FE6-bH}C8jW2%6UZVqULQCig;PZT8mN8Na0X&Ua^zpJ$3dg<~%NUo;1`=iT&!c z!Qp>U0Ji?2n77}Oy3KD%-9MCe{hxP(f`hFcz`@D=zuI#Czw^*~8kWM@@H|!`v(@54 zA5=67DZhC$$kjrHQdPDwHY-gR<_;K8y;shqIevn!eAli!A=AXkRm`r3e*7c1X_K{C z!m{K2&J*t)$Lxp97}tjv{+=)3U1t?8#^@H!&Vl_cNHU^SRHS|t)D^cZlRLbK7f~=q z;(bvajJRGEa`T4Dsk+pY2y7bk{MIo`ws3^iV__st8nL*ODJ8H8BrlTO3ALXEV+T7lEC6sFsRb^Hqpdvy3to4916^Wj4)V9 zGeu57Jqlu>vMZM>+9Iy!xZ<$h$4l2t@4egzeG<1qChm>03x|2)G+c2C6-S!6T!c(T z(Q>-j7rui;e>ZXH30JnJ6df}ht`HmR#QS-zaCnv0UmF?vXR?B^J@x=daJrkOu6ji{ zpOLC-v+6+F4z;rWRN>`x3lxnid zxbgaDe`_lq(Nwjc?E*Zup>AtXRDg8|+~Zt29@kEDoq3Qd@QAWbhhjp0<{j-KV&o9D zKBML}arNJgBISn>JK+gd7F@`uIhj9U++X%elN!fl^gXop&k2w)n#xrg*aQWX9yr;=WBf=w z6u~vsGOC(8aft3*kw;AQ@<-NtfGXx$1o=~E+LHORl6V>G8LuB~q9)QH0qzHW^F{!` zI+0~sgm;^3$S#ZgIqgJ0Cs?R7L8Nr-7vCGnJaHWm@K!dKKGd&+dO;cSz!Ma@i z5Q1$^V-h!lqup&}Z4No{ar92OdFV+SqTM=`?1AMvuYoj*#qX*!@E|jSo?6On)6ssy z!%Qn(bA9@wz2zt!x2N3G=c)a>Lz~t}kDy6^z4*5%L3MHlNSG)S4D5>RhQ`{?2Fs?i z_X3f0-L=)3nzE~GcgS#HkF^I#1HRPKtnR>b3*3yCNn>(82&J=7mHoKe2qCN@ibQ!+ zuOX(0z7%etA5FSDOd_S%Y^>MDZOU6aYgzJ-3-xVJZo5&}ReYiPP5&C%n|`GZ+;-v1$0=@yAk?G`j0`r1fp_tBu5{aLmG&G`Hj7ntBZS^;S)s74Lz>I)EpfP zjzz9W$(OGhqi}P(L5sVM`_=<&irr_D_ryNui>$k|1BJ7@22Rvik_qe#*b4tip@beg^OMj6VkHZpk-cnS; zSEyye1l{GR5zk0#?-P3PE7uyvm?VZ!?hXklRTRznCDBf5H@X277LpZDXsfUk!`q?= z4@um3ida&ElSZOa+3$Dg(E4#I0gD(fdVaMcj`&g2yaoJNfng1iXf0H=eeJH(9DiWpNBBloGpdqth)1W&vVVgp?gLYwO5eFGscjATUQJnryXqq zD4py<%(0iMJSlw%eG0;lG%BGF=%R#=NIJCL(uMor6V45V4J_F|nJN{?P$|MShu{@3 zELe>i7v^^jj$!zcGR+*C$m4G3;pW##H$J`fiWA)+>I|kJ`KS&5dZhoq*T6qeT=Vq! zD$BQwAm$sl`j-&i?`y!>^m~Oc`tHmoQSo&6FIqK8`PzQo0Kr#Jiz3kuFp_CJjj!y| zONN>x9}A}2Yy#;hotio%Pp?rYZJE+y8uqCgO*(DC@_vDD+S&5-!z3b(t?m5r>RX<_ z?fv`j=M%C3>?4W_&wO2Ud~j!QINT3xB^xrvl7#!Z$WpSnr1iy{K*Da~Kyr-5ff#bM zfV$)MhjqEzD z&D^;)M$e+}k8&Y>KHS#HgOu)K^}baq*_f4f-q)oGLCu$1HDUwVq;Q{Ek7L-4 z%JQr{#;ch{fqteu><-xOM2sPkel$!l_X~@b?{Cq^NMS=tp7~XOx9gVRLr>m*FPoOi zN3-bc47-Z+==RK&&+#&x+)-5d7edBPOJ!-s2@}MGqo6tdaIrGkBB#aw1@i<}Cryzv zX4ERlg!opD(i16!qAyPKkufb?aw)B64M5AvPnI*fgfBJ^*9i}qhf(f|Js{_ia| zDcSbBuk$q}_Yz+h!MXOh6YW0?7eY13tpl>smU0rE?YgWG$IF*`aCFP4&A3Kk(dTrjW99BtPnSpel?((+u-UiB5 z$xW7k55RK*L4ms2wsj);$}?D8OW*3aJbHtIEel_EVm?Ct0pF$ODxJ2c)Z5ol)}7aQ z%GD})E_0s(8lVEynKHZKoXu|n=3$R1^~<~FCpm?;33|JY*!^EJ9E;LZ zR?uL|O)vGC;I6M4fLktE!+Ei3WiT%8xV$dESN z%U4^`QQTzP+8G4oUjQBHl42B{rP3L5tvZ=kx-aZgxQ`Tpgr-7M=kXJn>bqSp+?i&3 zz!O!OgWkbPKnhO67yc$T+Bz&9C3A~ZjhAQ%rpzB%h6)$Ckws_4Q97Y<#Jt^FxfIEi z%2;o=AGm|cp)#OB%iCzNER;Ef6R93q<*sns3iGMC*G8pfN9nj>@jLrQP6r^XggA1t z1cDUmXlaQCI2*s!;ZTY?6h@&Bl1}m%!C0<+ssBAgv6i=!%$m&lB%2-eUIStzgO{db4nNPBl zn9E?KFq_H59>SOj_Y*~3q|NFPKECsbDN&`Ea&cCv<-;F(zPgz)4C=RH=MUTnz0y#)|N4w_si24wstSedv# zjc9<0w;v(+$6xS)C6Jb~DB`vPl4htjV-|m7p(+}G&!mcP{qMg}ME~bi zD{kuYzpsQURo#Cm?=AKn{2wB3q_9mz3Rp-4N~QiNiE2=mKcW!IXxH7oyEP%wIG7F2 zBien=`ET@30>+e9oL(mo?Yd%*VncdW{O*-vvTg+ zt18sihimWwP4zD>Dn3n+2p zj8Q#i3YnvjpvrAWa-tPbJh`gewVV@rWPS^m(=-*{>ny^-HcK?t&Aq*v1Ykt0l&ZPc zDj!M$+Y&xt2MNM`78$u%+w*f zKR-%IGQaNn$rT}uHkK6Qti0qJazPFDQOaJ!B80LYZm)QnA!Ykv9M&>qQ+xPfLwPxh z`mH~_t-;i<88nO)7YYod`qM^IQy9zao>4w3)kZn`Nt2@p_(fBKaj(J_`!r*cQIaa1EsnxCUAUl{$nN)t5d!~l` zq(tDMH`yszg7G;3zIFN0?UH}3{_;Do2wr{6tzX^^1o&-p*a3URgaenn_x!=6)EBZz zLXnRzPL2)1B8oMPz;KB1&_LHFJ4NFHb{9O4@hn$Fw}>P9LW0~I8=^V5D*&PIu9oql z$?OmG2BG0vhh+8)p@gJAZahk%xj%%M7YJ;ima~sPg`$Y4^QJ&6>uJ6Wjk}PM%&bf#WO`VXls`HN<1R_^$v5X{Nid&IOpmPX z#4$gGA#W6d13A{Gm#p-#K&R^%PkY|UK8syW{MI0i=)@M0y$so2Y}*%7%G||PGunz5A|fIAL{DUIvcRK7RG;|yQk#?<&E9komwX1P z)ygv|tN$bHQL7s;#y|U7=vQ5|=TaXnf_u$_cf|F2e&U9|u zgw}4ju+0}W3aomAEpIK;Zbfz*w-AHqCAz?Zzlrrg8Q;Ea8a*cS#;$X-N1jQ17Lj;E z>eVehlU*>_krn+C4Ryo&${(AE&kH8eo+#-fBis*`>TGoV`5#pQ;BJwGWZw(S(zh1( zUq~7yQ}gc^^#34fqLi(b7Zeb9(brjQ11!LN{y=qGC={oW zpu7P#)pw3Wf@bku){Hvx1kn>XX-4*1L$IjK7uz!XXlBN#5qr%7E*maq$pTbgzG{frZ=z^3cftDlhq=3EVQ2yK_irG?z~>XkyjtOxFvCt=0?TSXT% z*?BW&1R3^w8X<*eI`r07op#ovjj=W>)gCU&?NeEIH0s9hYbrc9T6h-nhT~kKv0c@4 z%TYLu;-^`OqE!(UCX#!$cfWh;8;z@%`y;m>dLUtj2%w{0Io?~&J1Xq9sK@(tv@a~i z%HQZcUEQXh!0J!C#HeShmpSJiO|k; ziCvqIzE!T6FY@#09bN zUWeRpeMs@VQYF|ZL!R zy)Y;s2)u+cSi>fYA?J%?7W^U11}gYF@Qx2u&BUS3^2mbYUNaLq96cZ{!OQI@Bkwz; z6m<(Jl}_;^uMHL_rjxXkYii$XbL66$Sj;*T798djXe0_*!6#ut?3}sEeP>uG5|ZM< zoW8qHsDnd{k>n6uiTVB?hEh}obWD%$6PNxC zeKY*OpA1T-F0M{?|KTT%QvE)27AU^k+Zke1x`<#dh`KPAc^!H;AVjBX^V)#7eNqHazu$YM`9F9e72tt3ADjL8~22&XC-c zGLj?!r1>s5Qw49afK4ar*jH#c>uWdLqUd96h#4<5ocYdKybQGk_w1`pQTh!w9%_7_ zMiuM|h(WtpO#H|A0x1k%FZ`9 zWMGeql%#I7>%k4GI*+^)YeWwoOO@|4U_?={et>tLql{!-R$jNwW~^lT*e^XKKMu1#Zs*=h_gcDN5xBGrrTv6cK*A-OEmzU5l51*r|joz~h z=`g72@eYdqx`L~%#1ioeD|=AgYFOHNtW1j3aPhoY85LvYDaPY#(cOIfolths=Cbz@ zJWm;O*VGhbd5|Ced$3=d_z63GI?DGq^c`h~xp=#HR>ysyXuuO%YP{8|7-mO8=! z$uEs+qfi#sn_!g<;7@Y$@npY90U2xnOPpx+`DAzau^VT$BnN?k%haiLkJ zA;-dUc(_XfUxG6nq`>sPP7z$VkBw5R(D8Z8cp{`PnNa(9_sFYlIG0-LWWT~9GlO=jus zk(Eo`U~HSSwrK9^Qz&)BfB{Yx$o0;d=A<_L0(xJ8I-vHk&`1+EN%ng!UDQSkBvyl0 zZVyJeQ*3|uPw6MSILHChU;pjl|Id<-4Q{q#_r2hYVgUh>{l8DKvhg={^Y3q{&E)e)neEHQn)tIsfxq%hhj) z-mvmY1pWS$A0F&>bRv}9L<8zSaO~pNR!mx#LiAp{WP>+;wG#g!u!Gx|+a&#YoxH{? z=!5HR+PV^AKYGV*`pVZfk1oRhG`8-G32t)fn}!>^2fX%+;ZMj-tq)$}j6K+`?IvKr z-9I(r`t7C*=m-$&gOhwo>~w>e#!EF|T>t(H-*pJniFZxofaiKj+iDFD>+on(kPlLL{%)(y1VFdD`kz!#3vv4+4ZKY@h>7xkC ze4ahquxn630{fvnfeXnERvka{vlpcDz2muPKZ zhxMsu871O$Y}kS%2}!}U4Ki<@%e0I&Th1+X!2OI;S%Zw5!)@G0%g*3|1U#U?lf=lL zej)dWNgB$%HfWY8B@j0kmyoLlcTxq zlG;ete!NZb!pPx)larj|(x%()WPM|$#v}vBw@6iZ6_O{$(w(J&O zY6dj%(0n`Dr z`uM&zd+;8L186o&H{u^-At@}Kk^I&#(0Yoc81(6^nbhoGR0irsN$|fHZpw9H2&?y4 zKXeE9Z`y;WJYs^+9g2e4Z{+c}7jNi4vBNjnCl(+V#()fR1cBW@##i3#j1f z&8c)#%{qXkQNo)l>m4p6>Z8`Pj%##LVl8zL%_WUhH@>{2Z{fPY6U%+kg%uUdL2<*Y zNF?XqsR}3y>QpoEZU`E4KTf;GExP3|B^HN|8uHxnf>9dyAxW~>?9wG2}E){ z3dAT`D;_B*iAc#BI&MCb^?+DB>YcfH96Cqe?BuVTK(og_ZWK#uo)4(lLWHW?m=2Ku zIK?#EeHjvSOQ+El%?p9?=f0K|(u*dvje3#i*8B!Lu9O)!5qkKb_g&~9cwz)Dh~M-+ zd+!RXA^mw0E%B3Vlf9gp`zaj~6SUY+*|yb1$y~{I!6=$0Ct#HwmxU{FVDsnxJU_1w z!}5^8gQZ%HK_P8ZJn>hiT}dyAd<;4CLvh3$Pk{Wjp9Ief26Z6eb1C362J(DS%o*f} zC3^$mE!%s8Qlqv~L$YbsjyvjSMm(c05K}1sjyYwr89G8t9GC+oplDfvE97h3j&m5! z@r2GVJJ|9UKj8hE<6}v>Rx}Nu<_;{oWBy|a#omVxbv^O`GwONc{J|io=O?8ThNTmf z;J|w3NE_vVyY=A(?GUO!MXA7Tc(kBwu5_D~j9^=hU^|OTI9)Ov%&oDf@VLW~A7C32 zhg#y9{5Zh5ZKC~k-+3QIW9y|$phpeOz&hW{jjM(4F5__qoM@MqXU343K9HZrml#$* zeo)W}e`queuo!bl4RD}K!M#0p5c?BE0=Fr3)0G;&anjks%)8}hwHYSb3N7uxj^!Ya z)~Srxv}?(MxRsm@Rb<+@SLW1z@3>-sm9~a-G%E#|HUeoL{+s#>+2@_noLN0a9YY{U z=$D|U9{^I?)U2(4(@Vb19O&MJuV-8Pst6^islM?~4A35X|1ta|fPF`}ysIUh<^tIg$U|!VlWtcCO?tYAx2R;`2z9IZ zqXS19f1we8yRE=d+ZlwBuZ>Dp2D1(S0o8YUA~!zC}n z!~&j;L5jXUiNY5+fjghVf!7&`28$~;2OQXvxO^deIk3;1K})v@xj}|TUyagpxSlU_ zGFjJoK^ZO29G*i6FsEE|UhKWsm~>YMpF~2RL^=wAreW|gjEq&A2p)f!FSUFm*69d8 z9U^lQbMr|t<(ZGZR`+~vQrv&Xs(8B=B)iuaR)$%Aw|@Pd1?|ckMQv`jN|rWwpxZLk z1AiUcJ0obXUba$}$<6>~ZzjoToQi_)NW0_6{|Xi&XxI>W$RH*URmV&1>;^bo4Tj#8B+Zdn*+c+ zcAFti(W8=Y`?EIjMb4@Wa_VBF-Z!(et@r`um2lU+d6}!s#I7nq^6VViY8;xPZ_@w% zZI0llcMMU-&d>3C;eKF!Qw#hpQ4KmI2yFYu^^B>gQ#KEwk8qW-sy-O1A7za?{2seAk2sABTEyC+Dx zkzW@VO$G4Hvu%;cM%el_OIiv^{jf|Y%PT5FDPFV0SiPX@$e6#o@yiW`;zL03A)rEy zONnnR0)vu5M7bT478UIymj^>hdi&*WW^P`R!1DL+hw=4hoAY(sG52%F@%FEet#>@2 zT8&BiLA(oE5$Y$$OFp`%pL4-Kf;6Ju+dTe6{0!g-4QYL<^}hy3?0X9B{-uk*m zFy}4TM;}l+P=oPzMUZ9J^YaP2`fsvzkMa#j&xc+g{>v*7I{j@5|J}iFrJG{{xn5wf z-;hR-a45SqA0OE0^v<_Z5H zvp=VfU0k0Yk*%y&Zkjz36;kk^t#WWo`$-!M**5X;!{P=-xf=`fY$K#tAsdY%QnJCs z%CkVFm4EIe0|UD<@MSXOd)=wfRvlLNz1be02hf->RKb(CiwC!yO8R{yiA_qhK)sx! z+n_)+CP;vgc9NN;_#X92+zQgR&+VJAg3ljgvfO__0uofqcwtMg4>Ui*IAE!<<`;fN z2c{|Y^fH?&wQW(I$6O5MCV{T(#Z{nSm|B~Tzgz2#`>3^wPXtyw#Kc$mW=)h`+1oZc zAcj-dbSsN#o?QvZUTMmpt~VxTuYuuI-}CZYsj6@;Z_`>)9Vf*xhuN7bgcX!&(^(Ub z@tn3ca9Hy~4T}>tvW5w9=2RBNPER2$n^QNM+{q8{BtP@d_QGAp_cCavI zOT`?rTs}>U_7tPZzjhI-46_m@ktGy0)Cv?>2xL6Kf-DJ-k)`E%Wi;z{V@hDXCAo%H z4oCw`Tc4{UGx7v4~`hqx<8M=X(iu8nR+5L*=8QNSGO=Gi` zrDD3SFh)E(*s^LfHvJ1C|C);e7pxP&wYoee%|}B8SI`=#H7#{hWK@uMfwV&*+9>A&gd4Fl0)wvn#QC zBspp37f8V5n)xCkYluu%r(-MpP@S;Bd@M=C>7q4Eayf~2ChdVD)VAWSeP;PSzs^TW zgnQen|8u#;vDQ!YEDqH^Lsg)ZvXef{#v@I;iUdhp^crILjbfu8(+YDV1K_0yAn8;- zAMM~JWf~Jh5WjCC{)8_$1{2+>#K8-rhEwDMJmUFE!-Wu4=B8}U$gO$HA^gP3bx;WN z^6|~f^EDD7aQNd28}rL44i!!Fbx=_U(Xi_zQI%8Oi&Ci=&PydL!!3Cf%e)IJ_Bq6| zr}wjhrpi~|rxFxQcOU`og*Kc_1thy=(O*Pj??>44vf*XKB{Uay^32YYH zg(Nm@uIydwUAk=LJ#X0!h^(w8&g@y~Zd(|0*W-Kkl^zHpQym!uUnW1|XuS>PkAoG! z3xuXJaMV_*sJKgmRn~alAVgNeX*LP+p__DW`y1pnbeeJ0OyP8>9Iy>L2R)SSv-$mV zYpC4W1NA7*b|a7quPT1zlQg6-WeI%>$A@)Ra<1Ruysxok6y0SVVMRv&G$n2WfhhpZ zvMe#XFi_GxMkLIpJ6U4X+B$*!+>s4LR`b#oe%zN%VuYE!*fXI)g{c&BYh@kzC><-= zcEK{$d6Da)^J7$P{(y&es3ffO6aGduSdSs%^RgM3A~>ci&5Ezt{FTH$X{KqpVZn<0 zcaT6zWle#83*Z;;UoV{2i7>WfX3b3D7Zp*0{uWRi<&)sxiCVV8s7K{r;6e5zjR!#} zw)qLjixDO(ztENvP@2U;+*`bXL%AWw=}Yxhk<1?}*e{X%an74d7_)5{-ICzo^J)&R zc*_0w8oH7>Kqt4STLFk||V$WG+Md}zDw8N~kCVWlZQc3U|inb0|Ot8U5JVBc= zdxb-~(No#9l~19^o^b#t3+}pDdLFSHkmN`?duwnJ&?k>-*XHd zq#<%7p{ayj9Fd=ig`v{P`k_I?|H~h!hVaIk^hBni0~V`3AAmLRUh13oyf5ph+?5?` zj}daFWqli;t;sT!CEDU?m3)WNIZyk7n;o#wyo+5)K~-Uw4=W19F1Qv^mZ8xg)uLnE zX!|tVymk&zIS*GEe;pA&0Vi(7h|P@5NpC@Qe?KeD~-rG{CxO$`zfixp$qWdMHw%34Y<%phd7ZCBAd)x2**gfE2M= z)F|kKR5L`RZWs@^3FsL6Jeh)h3k=W-0<+47xh`ma2K+!9LYxmH*W0`)Eh-44OJ-~T zNpi+wXSo_;h0nGo1xlnzTRhJNET0D?pRhR-+rlp$GVUB*ingIhJN(nJEplHtJATE4 zwB|PP!&82&h5((RkBeq(0)vp)^AaQ49s0pPKtFA&CbDu+#Q08f{&nZQ$`d$Ir z!Fy$ZO`7myI?j@H>yT2HVBH~v$S?zS#v!wX*{*5)Cu;nss@LzR!rxiZ3+y;L$!j{v zdsaR&POltmnPZ1iXUMxnd6H(@E?C3g;N55>L!?t1iefUMT|v4&8+=(nN^?i&f8Xu-Kcpge#%F%V>BEj-7LQtv8v zaH$-*K0YJ*jc&?w7164VSG|q)-JCb7WHm{%|JssgWg}n%*Yb=&^*~B_Oqv2B3}i;7 z3pl4?1`4@$5w(a~>}>!$|Eoi@QVIL~-i0_Fp<+8qRZQa$Por1%#XktOfrfBWBjh4b zL!tfDtX;{L>=fiUT1uX}9*HF*b{=|ACEXOOcvc^v^~T>Rpu(v}VKak~Og+=tW5J#2 z92Bne9`Ol{-zHRC@+)k;J2Hbd7Vnr)XYk+y4$_QReiHK-fz5tazs`IwSBg($5?lSmoG5kZxySX)h1C8O?h2pfuW~?mjO)Fo^~Fa9DFK> z-X3}fJU^!00e1!OjW0`-k=xT>0RxoB&t$8gcTm;p=CK`~edU(cbQgf8<8^wDxsvQw8=(w8o`JAB8>~)B^rKqbN*HN zr~^i*bf_h}R&`h_VQiaZ>yG42Thv^IrPg_~eDo>S*twnhL^F*1kn6!U37vfPxm?yW zBV*e1aqblHb9%vwo8ep0rVQdw;~C5BC;QF^dU^-biA~wwuNkddSe;Abv6zNZHf-IZ zAqeX+$QH0W_XOrsMD9}Vipwqu0_T)f-VC}n4koiO8E-I5{!{U*xKFHhv{B}GP49Jq zHz~>V*aKmmQBvR@_(_p_g^ZaO(YZT_f>pSES*;U7U7JpqL9lzjG_HuLQ_=AT!d;`@ zYvZH#ILaF##>1DdiUTx64YTXtZz9%83r!=YAi{yQu4pZgv~4G{Wsk?UOcs5)l&u`$ zyJ-t_EX3OocKW)Q#udZZpZ>!J<7!KlQ1#6PlK;EyTG_?P($4&UvhS*wPT%@dC8uS$7x*M{^7v0=jGv8z zf9~dSZF!Rho>N#3Ggow-Z#9_D=uXgoy`F>pIe*a`lHHtl0FR)O12o?x2Wp~?$UDEt z2-CgUiF&vPmO^~Ck>wUF+mEI3s$tcN zQABX=m}G7qtC24`tl^f(GT7Q>w~`ySoLy}C=s%z?XoaAW8Z7|^aTeU7uq*nOMopo` zi~faaP;kBpj8yrdO%U7zZ%@mS*zc5=$m7Tzu{HrViG~+L{=s*iRFSf6`HuE zjh)K5wGrj-6Qy<|*N#nFWnA4gzlpG)#B0^XmqUoJ`|GBmY|~I6SIAwp+s>JBs2x3j z16zbV`nD7Z;iR#F>&&{fQ(G&3WMRx zuh&j3O28`u*merb1G|1h4dfY$!I~HZ3DHe~G=_(DG=%NoW+Y~H>7$%ftbqZ=JAOkDe)zsJ$joqf%R|u3k@};A-@yM9jA*Bd z2fzCEMkjv*68{E9xLdjyTL>FE|DP-{wZFAv%6pJBe2$De;LINfVf z4uv-iJ+9lXy|?fAW;ka&uRmX}?R$Q#hEtPRGk%7nGZea`WXs@{yb4BA+mmryk=|88hcEAeGf?jpv-S`NUlqBos5^ zm@eSJx^IdF!9MBeC@8L(mAt+NS7Yt)mV@In%PyoxnhtW!u zqGMbvlNIhlybn=!JkmE3^}vGmwl8Fq%#DNw+PAV2N@4e8UyGqwqEl4Xvv9Q)F-f17$Zdh``J6!lst)KZx@tt`t<$z?<; zHPzyo4_~jCJnuVrf+Ps5(#GB7GO{msUM?s@f(^NGC1*1Lc+6R)(|9S%ih>ImH&~Pg zK-E%bM=lZlTY^zk=x&!t>7m!KJJ9`MSM3Z^Lp{E2 z_J8}DsR_4(e1O|F?K+-VuuNaaEQX%dxjaC`}6!fDmMV)JGxj+K&D*DVji-)i6yEsxY5>qrE6C++|L6NHAeB^4X%R5n|%W5{pEMe>WVo{Dc7cin$R_2PWKC8kM zMjEI;R`>7_T;V{4cZB9(=^f&jIa3GPW&xeZ9h*}jI@5=7 z!nA$6N&$pmXrYV0p^=$aC-TcW-Euszqu zq7dTF2*Eso-m_vgLl5ET3(P5bDNB;v$6Pmw*auiS{RN`_n}$KJslt$k(|*qjeZ`!K zRITAlEGl5X2^R4!r*m!Iws+#8a-2<2V}PcKdf%Htjw$-sH6!og0wD&(TR&M6b^$Y$ zST0623HfOBqO{eq9Xz8<$WMh`F={R9X*D`qjiOl0H1NPXqM8S6RMAsLLonxwf}~&S z*%mR2^(GZan3ZVsOyyL)bE2k|;*2BEA|7$(`b7N`Hciw#r_NBP&`0kRIHygXsT;F^ zL|0tQOZTD??aiSVcui@!Vmo74Ltdv^N~HurSMV6Tsbro-6-{FMg;MMCO4JHTG#^Z! zqfV9Owr-m7WgA6}=ufj29M`GmiMccT@~4#-`Bv%U8heSmwX)yZtoZnBAr#0&P) z;TDtw*5w24@f&Zcy`M)<;!rQ-8m(6jTXGkUR&rKH=Hx6KtjM3rcwdw}fJVIEybaIq zIG-OnZ67rq^=FomlZLjyGgk;+?jG2;eP@*uO3>bm$;w&{9PLsQ^<@RafAl@fw|b#A zNiy^`)3i|@VKgT_!>ylD(8m;YVnVt@D#0^9J*UI|e*FHQV?(K82Zg~QJ`W2}I6F>TXU zI%d0fWYk(pAT8wDcP5HK5Ki*UgaIeH?fY!~*pb+4wHEJT=J+(8((?B5 ztF9g0Zta5KAJ1Lzz>)hiRig#5{bZ?C7=wnGM<%H$eervtFyhKM7bs{7i8Jvqhisca z#KBu&@u-+^r1$mOym-QpDJz31N1ltmam@N(OkwZJtr*2H@Qu5Ib1w?ec*)qA_;G*5 zH*PTSQWD5Tj^3Sym*8(qkmN~k8-tTiyWC|jCNHNgPcpfTaG2{+XX+c2lh18eX44yv z!h_WvWnfnpabskYGTSbMPWdL9qbf7oJV&U!H3uH++q`M%`S}f7kDeUQB-2JFqEFk^ z%1R9ZL7?AUuuGYN5?OXhV+Em63adqe4u=lOaAp2slyzuv2%JTz>`i^Js?6h!y{gVP{{&?Sb5kqXt5?Sg+V2|mnjzJ zab;6g)5^})^WS4vw5DI$M{3jWFe5ZfI<$I}>g61sP|vjnKJYdL94S+t(W;pV;dH5{ z_Igxf6cRyn&ZPU(RwuR`YpQh@{*;0d_zgM}3k*JjD}`EcqoUwiJ`2&77FvJ0BM&eC zm{IPOozqInxZ`p*hbEI`&)w2g&)&-VNQjT)id?R)&TRY1@&r~hKd#QcB~Tt6_$5ZC+)5$UoV6m?jNRzsa@SFZ@t<)7 z@z>3#UsGU#(>c5rkApy0{0_oqE-ILJLuw01U`A$_5+=5W$gCQ>Qz4eDrJs_FYr?L! z=DNV%b{T3eqOdNvy1qbUzDD*MSb5G$7b1U)zHg(9T4#d|p{V?`QTXI3TN-??8`VK_ z(YYs=F~Td_vT>@a_{*gv1dH$H*MZ>+t=#ndBqYa;w7*(Xz& zaaJr0jgqe@!z90xVpYrHWkRPFZ~2j2cH9C^&s0s<<_gEN$+jQ~vZjbiutxEMrpQMl zQb#-h3k$RuaRAn0DC(ql>ZJHab#v(#SSyw`XT+T~$YDcbw1Zwt=AFzA5t1tOdF*a$ z&$JL+SE{1g@=H1hb^W@SJBz8kw?R!mx8n2<>h*~SdLm6$FUWWt_(e=!iGr5fi&&=4 zZFNj6JP4Qxt4Qjw9d`yifl(@nN%K+}&E@cwsy4_C9`l-YDl zJ&_3qGsrTkT{=OtMyYT(_TC^3G^H+`;^!+G5%$ztrE>UDKv>v+UO~T`X1`USZTMeL%cg zPZn>~by%`6HHB8nYCdVNM6K@}CE zM>=Jxp4|hlt|2%aluv>$U_vTezwKhQf~ymY#CMkb7oeY%TukP5Z?oJd#me=<^j<_9 z6sH=>`i=6)Q_Qi)PPF>Nus#^A`m2b>HZkqrkVtGUIaCC&?GH9u^POwJqkyUsDC2C1#<-d##{ImzVOjv3#Y~&Xbms38(LF6 zud?vgIs;vQinqTlk~~DwZF}fnT#@P!waEW^ ztZ~Nrx!4%^sG4m{$h51wpDWfmQtX@@^uY&x@WbdUmh%uHk?P&d=Jtt1eZM_gcu?Qq%fFDpp0-Bz z|JCUgq#|wqZO{57lfAe#DOEn6Lo11TmvFpjq$8Z2X8{|L_3v|(0+1CRvNr!TpTCW) zBUjXhBq7mo{fUGm|HEhugk+z9sxKOhAIfpsgNbc=)n>ZO`8f0XeHyUc^Y!`{9%v>X ztCva7Fv0AeDr05Uge0?H3J5SNWumsWxj(b=xAk%)9TbzA$f10xYD}`^OAr=_kk=Y>|w3-ehxq z1&PZL1?h5Sxmn`TOO9sY?-C}nrbLR27#3Z1qziRwm8S5d(Rq6(Xf&AtC6)kxCn>#> z(1tCd#PlQ$>Qq#?d)*R*^WZ7| zqP(2f5ZuC%LFYR1iC&8{{vujmEg#h)63t};$)FR3s+j9fyPMlx%ak4=a<3&dppFmr zHK(&t6KR<>z%AaFYi-QY0+Yj|S{jNkL|7%A6tOy&Xep$y6yw^s-6D0o=Z$;7BQr_a zG_P9NG_Ualltw~aXOBQLZM9=!mM{t~tmaFdw`(aqm^3vitHD~|3JO+fq+3F8Y>UFH z65C!-wW~$q=;T@>Vm{|JP)=y{(l{dnFf)@J;f_sZ_P=vX$qu&@@d+&@Czaq!hVSwlO7N4=5IxMP%c^V&(SVHlH?-*ya02^B8@WT)72!j&Ljw>}{urAQh zs}PfWKGMC`a|9FeDcaev2vW!G1*!3_$8WVJ*4GKr=V?zWV-;APMz#m}0}=A1fE5#u zYQ>S2r%`c4#^Xd0cVW-?B|lnHtGg2LfDB{D=hxX5Qz9ge4WYy)42!cNelnxs0k1^e zfFKCMIc|jP+!~SMID^KxOybla#ia@90oQ=n2J^KU7qOoPt!qyH0`AEiM31&J;2<4q zl4GYBxlA^A40XFEYPwI|dPZncs2qAqc_2Cy{ld*%e~#%hbtyp|aq~O4Hf`u9%DrI< z4Urt@v4sjR71Mm!BctK3d9a8YDB~&Q;k`mJZtA;L=CYL1XFMS>?jRp2#vE6~e)puX zgsaF&4k3~3=N*RSvcr2e+WZRBzNoM9x%!JpXEHo4xgTAKF{}>#+ktXyJ(l2}1H?Dz z!~1z9@X_K}yRSQ;3$PY*`neI4H$>fH2s^u=-9^!hr(v(r<rX!W55}VSt;TOR$;RR_^!45UyQv|V5Qx*wHw>E zZQHhOCo{I4RBYR}lZtKINySDb6;_fz>+F5bKI^;K>%X2i^J2VX^xj(U?OAhc6F5c` zIJ|@~CDm4l&Nns)kf{AXo82{0Q6^cF!$3ja6mwwC+Ll;YTQ<2 zzDg=_+)6iy6{~6psdB?itb9FkfiIOp_EKq>cAH~&a48kQVhp%R78}QcMr|!JzsusFSro;zCMs!~!P5IE@Of(C z>Qs)_71fS=qXo83yFB$k+GaBX_{(%zpv@@>$Gc8>DGr`zRc4lWRG%^#L&-qUclroP zPLfPA#XJu8vAqr7!DID&wwm?&;l^uqNSd*#pX7R|e9+u9UXmOIOrf z$Ll~IfO)PM^cGE{h*p*^m4{NC4WoC zl85b7)~OAh7oK;1vpTmi39VlWF~k&75zC;ddPV@=Ca~I)?x|P|XtA@W0p+S|i!_UL^;YcobJM>DTM+veG!v?b@LB2|+QoC9BcC>;P66>0^5DK^9{y{y z?=SzboB&RTH2dEYg3`By@E;N@)SSKkacQJ#06cJy(fvoG&16H!X&aY@!yu9=evii$ z*pfS$prm4z$0Zw40t%2ue-G!G(M4t^+JMsQ2H9VkpJSYfxG2b`3)yixBK%m&JHq<} z-+LKG+!sA}u^c7UcE)q@{X5$|<+ppf`@YTlb`)?M0JTriy%PmlIMx7)TDuHcS;S58gFzdn-U2M;eJ$PrfMcKd3 zNN#_{;G=7ZAHJjVCz=vWS&DDjXWsDVi=(_N!Sj?!pMVpJu05@&nV>Mnsd#2tHgj$qV1ZqNn$NO*KYx0C&TdR=FqUiG zjDP+|YoZj|AYB)^0j<7f>QrdwKy%V$u(HQowDSqYcqw6yRx8y8nm2@M8PjbzQmb}?yz?a0QcK5PMdN_oIWwFsT-l_e$(CM) zqOej=6QOW9Tfuzl?dHfh@r`{Rb#>s!%`aN@~?LNSeviQ89*=Nrix1TQpQJt?4RVs*ICab{3y1s<(x={W;-mT*d{+dwMI( zkI8#u(CZ4kd>t}^45(ozqa{?F#@88G2Aelhi>GRJz%|Vru92s>Ph@`>b+Pr!-8WispqsRxPi6{2V5_x` zoUI<%JHq}5iPQ?En82#s0V{BFiy=va?_~%0@ALe)pox|Kj%-9tPyib8!C2&8oDbjM z+FtXBe3-jqyFdq&82)wK?UXh7LkDZWd`UEhYVuMBfFc-=iqTTPv3-?LM zBwIhlTk^ktvpUr;bba!Oai>AOA=P^{05fzdQ{-w(c;r{axq)^%a+Xru zAcox_LIew7brRENDjn?o!tH|;UY8w4es3XkN9l{2_chMa5I&a0J?;!qiy&7Cu9~g#knN zhtjmJUp7ZT6$uJ-q*!+zDdqzxu94p?82bbFGcZT4?HH!)%VwcKtqpQEX5+D#Vbzq6 z)X06U5Axb%j#I~M@~%|?QP0h%`T4c=#n$$4vtfG3Y2RNpkpSrIHx=FVL>@mf1q>%Y za$1~M&;W~&7g(M>Q#fHndL@C|^Os<#i>Au82H{PG+h&l}gS~f;tVo55C6Ok>f6m^zd~x zlwWI`;jU+UY7>&vPh%yIgcLV@B|h9Wt+rY=JL;_*Xp4k{epmH>DVpf%14!C@ECbsL zB0hgObceryE0Ul?U;lau96Me9`iDtd$c+2h^lj40e4DiYVN+Y(-q_jepZS8Z8t^r-Z=2v@bHlH1G7cvFP z7D(whsD?m{w%P%rn^gm-_ zbi`wPfLX0%wIU6fCni#g-&KjSIj(d&K{Tp>5{8ZIycNw=t7=jfyj>8?q^20WX5Et%VO-f@*}1k);~7KU zF;nY|hcMY|FC)Oa&QN|VoelD%msdXM4pQrSQCyjGHr(ucmd6%l>_gZY*(J+Rz_q%> z^vgujrW!Ms8wz9HCD=Z^=G~F)>)rH+_K>`d}s93%I-kiKdYL z#u;uU5=gn{6EIWerqLJn z?xPq3rfA9AbjrL_?#Aad zigQc@Pj48?hR}RbNGc#&)b@{oL!O)92&U~oC&-k`lyU2a1oxaXA##aJ6^{%=>lb}L zpx{M3_HWnm_W>QGj-Lo-1|@xWuRDKaYzkWafssr7fZ?wwXlp-xtmu%hiVg!=#V+Y$ zXN~#QiqgngaGrjFkaJ0TjHVC;v`7t*3LYgA{vJpCdF1s7cRrvP0nI1t0D80%*27js zneV6e*Tf21k+{!fML%AvM~khh>M*bzAs1oa^ziz5!4(&mfQ080sd@}^VSBqNkR8qA z5@eOZWQQ;(G$*$0j4ZljJv-u&FR1>Bl0<5x1Z6wLjiWZt^w5T~KA|ubR8ISvMEUG8J7062;jlHw6Ri z+hQkjZ082xT*F_~65n3g6oor!uuP>&1A1JX#5tdek4jcE+CvUD&Qz?#M(w5apXm3* ziAzk=?^dY=0SJige;0{0jGY0--|3QK=BBpB&c?0)2mAlp_|N_Bm{7l`b;@)XT?-0Z z!0AMU(-PWB&}n&bWD>2Zq-+w!%{F7s``J)gmVn$u#ht`Qe(W5;c)k>zO3^yUO=$*1 z_KEo2m}QmG2Mwmb_qv?=<#+Kv&;I@R*Nl$UK>V>MFr-*F)qxQZZNck2t`K#LbLc!J z34^u%uq?0u119DgOhhrT+F=F} z0pk3P5)k7d`p>Vbh_%0-`m3lUyLZ3j1$V3ZrMu}dckh3tAl}kY%~=6NFWKF6g_+!? zrmPZ$$CyZ&hul{m+|m=JtY?jMG#k7YFX5SKb0griM8g2q$X=GurLiff3$~PthXd|p z@MH6Grc#Radt&`f@DS|TXlUUYk5p8E=7Z3>7;Nbt7smokMUN?ZaCPQtMb=S&?P7dTq!X7WM=X3d-?Ps4L1C7g?KYdQW(A^9_fIZu)*5!$jclPR=g zP;#MG%8V@hEL-Vrnn|oBI99^E=NNLBss|)qyj<>vBmL{)7y`vu^H#qmSVW|BF8#uh zLsJLz8kil%C?hItZ~+UcZB?bYDs+)^GN+P;IG?8F2I%u9YerjwI;dSN!TJ9J%LvvDl2>p~S_GJm(B96s2 zy*OaB0ba+x!-jw?ih$e7{E%^03QhLLo!pw&;A%-i18ID;btPeOx<@p=CgoC~yZpef zM&mvx0#Uq1ER+tPQi?5iH4au*Ep(ya;QXpk1KCE+H*`tBx8?vG_ zEN%@J|KbPF<;C|n4>@wWy6=x%l(B{=yE7#x@GjpMoe|EWPmC_LtA2%~6p!AaXBz*0 zb#T~Q6qV^Fm7~eGK*Tk*$NkQToh4aO11GHK9_T_N{~*zwRby=D5&i}JBlE4e**bfH zkxgn#tG3#5uf20THu*w7f>Mu1g2neHP{7GBv~Y%iDrVIiyu+YlzZ_PAS8};^RT}?h z{YLH^vq&o0j=71VciTB-xeRdM`uTAVI&Ul6Wxdg>{=0FF9a$C&ed=Ozs2z;_^?jwC z;O_FnEgSl%;nZJ8^<+E((X#Wvgu1QCxWfG-QoN!#^yavWbB>vlp#DJjj1MG_Lt4fA zh-CSI!<0D*;r3x`FB3lbDG_kXi{bkwTkj?F&B(oI@xQ3r1BMiBp>T+GvA#4Ss1}ZM z(xMx3@^B;Dz^%WOQ$ihzUFWDK?FTUt5OzYpET0u%&CzA3+Li3Z$cz4xTaOhlS8Qx) z{TS1;!BZsoZBK&fl#5!2EB?w~*nW>_PZ}^(1a|3IXw$sLZ?(Z6w*rPqYQsm`!=^Ir zX5V4|Nd@xUf+C7tJ6)8@y?&!pIk!8foq4I9xTA9u)nOR^M{mSnxD_!aEFkE%9M3be z`f74YsuD6|<_+S4!z3BfIkB2+3B?{u_y^HW@Z{VY{j^d;&pn0(4c-9zwi?X~>cFhy z5|oAh$1P!G**d$HENH*Ls&N#$9f!~TQ_hI&;tbNGcxCnK;_Ev|1OrzS+&ATRA*p;~Tj38h+S$zp(dB2^ zW=YL^%}${n$7(kEj#gN)Zq1IySh7EJ2uFjrDt29P+3D=;R&tQ1YjFpzuh0D!$u_M1iqCF@QJBmz4K~L}sE6YGMuhqKD z-)|j@YXB#BtUc*+H0{Om2;zo0F)sV~!m?$~RnJ-cb5MN4M1@OmY9;n`8}FX2#v0qW%+(Pn=RjowEvfnmb5*<6<}=p9g+Uupt4l89o27}^NU`3 z91<2x=G6*G)s~nnrA57ZwG9eQ#ySv#1gh;K$#y7>9M^+W?sy^|@^b94wwUSg?kpOS z$8^Zb($%+;^y5EmkVlgKC6748UPA|{wnHEA;;OQp*u_t;#`|$ZNz*E-g2FR^Bh-Y~02nF3Q zeFN<$(~4FIfm&brSSYrji#3u_$t?+DdNQh(HHsYdS!csV#F!hR!x)B&|<< zlnl#}TsGgEqtmiR#->$`;+@CKY_Ry4LzU?8O=Ubt=Sm_>);$Udqvn#yMv1#7B33Kp zEp_7Ux_q<_-TCMsJ!F6|@17fi#7dbrG|yXfW3N9mwdnok*R>FZe9NXLG$#9z?bD#IJHIny~;IDUn;^aF$UX+3jX74n@EG zjBNe!gw(w0hL}7|sAiNfBPK^~A0<3`*@k?P$q5VzGNltJEPmOgO0~%JfHM zIn|igP_a$B*OPWv5i6CCf3!jtO>!i~&W+?wS?2@C{o9VNVh=>$Sph-)D)?6W=X z6S|$THs$6OhWOi8DgBg|VUD|etah3%$1|)S*d3kTUt~6)Bw{Y&*D3q7j=n|h0SFVS z_cGqym_oH=evzFQ;x+3~%_FM0D;>OxGQW9_SxBUy=$fO?>8FNgfK5kCowb7B-O>v< zh^N$WZ%OtOx_(f7S`7$|2)LN(($YVgR*oaBt^Gc!T+(e%s@)!CJ{Q4-h zMH*Fc`CwIKfGvUTdb?{#FDb^>ati+7TW=ZNhyA0!ULoy-`A>?!l3)J_%VRjwyKDV6 zIVZlu@@W3|5?s>?U~B&WBol#4c9K$?tf9Ouc@(W_NGcc|yLS6GB}o?IK3rzlCSKZq)!zY}-04KfzW1MCbiasE4_+F1y z3S|vwhW~^I_kffkO<)+Tk@>PT!Y%V^-C1cW9-qjI@0w0UjFuU59z!IA;o3-SYLQGj z=iVHR6!N&AIO2`7#Qz+n9OQVgFeiB@r@TOXR91ObyLLIKDAj;OeUV4%8Dv`d4_5lH zY1J=OI8}+B?dBb#=79%Csz+VYCr-1eO13YdlXKwZ@FktzkRXJkO;>xSb*?i{NYO(3 z3{DmEuR$M1#~_F1*L@C55QY0ERtXX64h7o}o85tPgHIfBSR4*O78N%RRk2q2f!#h# z-Y*{baLDzNm^PyV_lmO_djWY7=Y=KLfYhjI@$z5D=55F;^oENDzvSQ;9ivzaN%D>h zJOjEyOn6+yS=KL4S=T5#|Ax_*~3eBVP_{~?=J6X0s~ z53e#-T~`%P9qH5JHXT@FP+SiUg_N#2l%0kdCNc=fBKa64Es$85^-3WPdT4faIxxNa zJo#jxt5l%!xEQffCQYTf=JyJr`G%i63thwaw89_m9hc7c%bVMrkLNzYF9=5hZ?xnN z98tuwB2SzpIt#7ti8dR$rW%9z#Et>$xRnj26O#nykrS_7dNIdjK}LxLL{sWuU0eM) zQ*ejI4|l9;8j~&w-iR)`Z;pY>xKw zD4Cd@q+5%8?UmFWHafIQ8V81*$f38k2ZQWgc~}}bSY1*`Xj_iK>PZ{N8k>!@KI`~m z9xH5BV~q~aWgYW=&1Dj5inhX0eZ~>CoViU_p)xZ)`AlXVtvwO@ zvYr?HlmFO&8moVfR$0nx&+hn>0K1f-3;F`?h30%6z*fIz+0~%9g`px%qb!&tE|asp z286vl8D_@mBBn4+HnZFG{1_z&9-}p?S>d{UjqDMRhxunIuK3JB$W~`9YSd%niX-)u z?|h4x_+ndV8GeL3dk1SL*6&{9*alN95A*KWQ?tjzmKaN~wXuWTEW3n}gc!?&lzWDo z2_amZ}!h?!Lfp@j4( z*Q&N&QD^pXVJIsls+h~Z zf97Ga0^={7QJ z3Y0Qml}$rI2`RneCyp5eCot_+T*}U0PI1R{%);6mqR4bcRU~~62-m71Z-H(qJh{LDUPpQcPTLlnu#=IL6sRce*jsyV+VCTVp=eQD?*#pE-`;%kpPYWLeh5+KVjx=s%N)!|# zBtViM9}l#63i5Mb`I#cucy~lxS?0Dku=Zey675bE=CdNM%!$!zyEe|lk3s(Y+I>i{ z%=rFwq>pHCSA6QKA*rUQHL5N3*HfrgM*k;GUe(5C{`$d0KmXd~rXbfJP?Mo+`~x5K zT%Tc_0!-i+IAmXiqnF^kLdJ?DZ)x+!G%xDPOQFVdE)a@xy8S`NU9wqzLcN; zXvJJ{3URK!0W}HV9@2jR0chFTiaEF{yO}%xzl1xrcf}<~q%YTc`%)NOMyH5~2z`9H zVNAr#eowkgEQq3vm$Nn&8r?0|T;MM_)Gye8d9ije)Gwefszbjmo;0E*x}Uo{Hv%5d zKWzd&-=0AG*_x2YJBW$G%)pf8SeQqq(NHCv0jzRe^!o@mVNUVb&qEpJ zU(@#)r;YssmYH}Rbm8;CWj0SFkbNoZ$4FYtGBn{gIc3$^f2@UD-BUz<@HOTrtI>2t zl`?O+KwN>=jtWm=YjCTx?*dYzlDvz%)vd*4S+7%6npNkjQe%uAR@5&&^H@sgXb(Bz zCt+o@*QzRbw9Qv$vlU2}H5*QJjJMV~E;JIW{;1l=6_(RP87SCorIn>avudfxzXw`W zp>x6IMrqaAq$XJ_7wnVN0&1S~+D6N?5aJ<8Fcv6_2ti4_Gt=B>j433z;PQg#4~R#_ z>5R39VOaPy#PvqFTG_}WzjetDg$S)Ni15g-!>EvLVy5a_8_8 zuARZ9Sv}I};?$;JaYg;U2YongPC;5R86krVks%_#RIR~!>P!gz?9 z>7uL+=FuBG!#$I2bd2i$Bu$39R9MwF=*twA?}+Qcjt@+iFQ(N~>(LWx!s+6!gni)t zMtSz3EmO2MO=Px8%h+3yuLf~<`uukPISWcqX7V0_1RhE;*%?&-6GCh(BKQ4}H{jsX zodEvP*P5MK#E@^Fe9%*TySr=yU9KPy8;vVr0Ibz_^k%Tuq?C|db z#zZ?&SL*kxkN*AY|A*Ds@2^Juo9LusZt-7Yd#uKmDy})&m)(sm2GqDXjxDY&u`N}l zhpY|#a>0V5ERE%)RCejF7w5E3VXd7Gf+Ur}G90{o@M6>Yp z1Qh8=nwJ3m9e_EM++8p2oxY4<18I#*{y}E9CNjt5)0l5>8(uq(?8WHd=?tPDPD88H%(ju0lROihrCK~N&tu@kVH*(zNnY3BvcRTEFIr2kkOwKC5w!~S@FGj@u zLag5p0CfkoDb&-1ifayK21)Y<^Y}NS?RLd-&%a)*Y(84H;vwRObt6${E==tGt8yly zpy$>8x_^wWj@W+8^2m8lE;?^@imr<)cvb4PIyFYa>#H&+YxlpK(4&_cpzY!jn~ZcP3No!e&?m^!wz$m`C?>g7z% z%9NpJDc!4`58Y(nTBR?FV%24rH*j78Ic?JQo<-Kh;>opsOh9ovVV7lGNIEY1)~3%3 zk7b3b)gDz021{RzA@C_y1k5|(d=`my+b+(Mf8r?{&U>U_>!s@90cPZroBAh{x$5O|Tc*cXMd%aDLvJS$u~Z^%wSF#>a1%<)~8@0D2~h|?(c zfyznq%QJ&vF~2Rj>d`{lc)!5jzVcP6gqL2H?r?LpUX$%Kj77L1_S7jf2dhxZfDx}y zBJ{)Qn1A(-k|^|VN6H^P8+Pdob!sh%tbh#7Mn z7T%vO0g;iDE=vWHP-;gu6ykZ;E! z-F$w<)VX{M8hhV@#((H({&l-~Iy#%Xxcq-^Vyv2->XH_kzdZl|7>Y(S z)?5Z(a}%Wz(-c0I4+5XD$5hf%8)c-9WzVA6Av4d}xetFKdd!i^@ z^+D@k!x@71@7pPyhF4G8kpA`|K54As;)^QSS{u~j@)_Cn0k`w_wrT;g>1(PBW4%_lUBNezEd=#v%go?qo|d3$?Hlj`Z|C z-b{)G%IqO84z>{;h*k=HpuOEAQlxvRt{N*Xa#*%DGRWMhlQ2iQE~YW|SrMd^O|d27 z!U{s0ka#qTZA~UdNGT~(o_>k8$lxc^z-~GF=_#4`wKM3%+`QlK6_k6uG7eh$yPsGB zm_w(I(s`jdfj9$~jiI**-l(7+Q}TyeuV=W?QJkc&5G^7hY;<@;>hm~K0Tf(P6nEGv zo6Oc4Biwom zdd4cj43e)y6)zClvTqiZ`4*q!G46cf^2!|!JHhhP+*toP5_T+J`s@M>1QhXI*8k^{ zUc%Yf((ao-``^_`!j!_G5>nWgC@eaiCOTt5Fl>nax>QjlCyJ?vNU$y0u-yPebt!pi z#+mL56$4x(EMb2*%WO-mQ^-Bt$zRsougmGzzusR!j)B%F;x%OjM)Z+jtJ-#sRMb?o z>u6Fr+HuF6U?rOdibB1v4)Q^^Th7z7uFIS~bqnp4Dpp;fLpRuYBVKALAG|gsN;X}) zN`yb>((G{GdhV^{AoAFs+)NKHIZ31LfOM$zB#ToVN z=K!2+=Trj?U_$6%$>NNnnjkD{p%se=fLC|7uy-k6n0OTS1q1?dvBE2|+6~-$Vp%y zBX$0MXhuv=L$<{8{5Y`TH~hcfy-1V}wYA@sWy1eeW%+MWOQ{;V|KhTJDlov2sWMQ5 zQE5@PnWIR7>ePxviP)jR1JL0x>yyoJ!Vsi$GL7yx1ow-dARk-n%!dZ+j(=|i{L1bd zfV|vIHinASduy7@{d=v1zJQK7s!ylT=9>*uLC4M)rh$3=lWs$PFLCRGP)r>n}G%KXZs`9|mlpC+~{Kr#sYpYYlGIf*FwD zmf>hbkF<=r|K4`ZWxJk~DYd|e7zJW46CPHYDm{v_yEsPSjG+~_qp?=^iB@U(4Kid0 ziD}cRyv#MXUuS=Ai87Hi?(CajJtQ`KgZ;z4mk7zaLE%!bKaVtMXI~ekH?dG8@t$V1 zVnA|5pGn>=UY5=jteE9@tmxXtuo;?CO2LF@ATu_(t@OOP?O`DtC@;v`oTe7G!>_a$ z78;hS7Y(DkP?HHy+}m*`<3$GXGvpT+s-g)Vaf0Grthu7z+bx(YSO#)8d+6I7cJ_qB%j5{S}(DQ zZT5gHrdgY}O13>vZ<2|apB5TMwz3wmmb{~`FYGX6{eG`HpB^5roOF&pI$AE&sMg6G zq)2(vwjzutU3nnluG8q;#mg~`u9K&hZ0vf@XD^KeLh56OggeYQPN&-OkK}q z-^yfr{t|6d@>0pyjBs(I5fiCoy$8()DO%ym>aZ6#+XGdJisw7FJq4uj1%MwHA9GXu zV4Kl(MwB5Cj4iSmglz+MXB4K7wL1bhE&d=Yvoh~55d}i~(ge%*9^l2ZEUTmt<}@n4 zgZ{l!FcnJ_4=`t8y`SLeNS8Y!;NyB$N#c5>UX4tGK-Ia5S=)6T1f- zg94O5+BN!x5pfDp)_9H-q3ZZ!S8k~fO%Or~xc(5nJcHFBjkS)!-aB-|WkYo`yQMfj zRrdtX>&1VWR8G&wPb)iSZDCEvG_~Pjc@o4JGg}Ay&wMcgXC0Z}sa{NeB<*R6cigxH z;pfKK$gu>Vf@&jFH)UbiSlI$pbqF{B|HBQghTrRcO$~pcoL;UCDNMm+qf8Did_sOO zBGDu54s_UIyAqz3=(thVcve{`W41)1 zsV*}+7RkD#RX=GYZ>=5rfb;UPwy)A*iJ%?OEm=I6s_S~N^ZE}`%|=DAFVy#~m-Bt= z{fC90?}}62+|I<@`G0tn8aAq1-w|_bh_6A84cVb6QmEsgrdJ*EOOhgTu+Sw6wjwdI zB6}=pu~ChDNmj(y0po@M!R4D4)?ELa_zPD}lqO2C{mg^=s~sP==Ny;ko5|19J;6_q zI|3YLx_y7VL#km%Z*6iI0F zyt+oONt;V#zUTrHqVE*dtX3){xj8$SP=Yfz^?f~Qn`)bPANG|BnpTY35}CKQ#Z5K1 z*wY)6@y!Lfpr1+hY!5zfvb8HJzxQYbsZQDo-D9$Qpxs?z z(8PlrJI`ubmfM6PEhr1=Ggon_^|*dC7I9!;sWqV$SL%SQg#(i#hixKtaDa98A3kEk z_&IABxibuTTjoCC7B_3|z-`Ord&+;{4Nv>eUnwvYBnOCM0zpe$z7;3*{AE8}8=7r0|%Myy{XV za=9;u<{$kV)$?CVG=8t>j_bte$E;^t1I}+>A50Mv7qc+4H}z2HKGJqd3Zy5An5C^z ztJ}tFkJ~SKP1P7%ZmsgD(&w(r?)pUO0tSs^(H(|GtmUvSV(QmZ1)AJFT4Np6XtJDD zogt?!v6p#@eT6nm@_mSh`*ToWn0yH=$3($@O>s>M`Kj3)}2Q{eU zNKrEBkKHe7P)A)!IjTz1@CZ1vVEXPtlUZ z8_~L;;Al@UXKDDZYB6wh<|kbd&)}oi>OV}ZLDfmU4#+ff`nw)Erv^H&VIq?f68nhz z>cny9QU0`SkG?xBvb=R-gtTM`=y35*%ip?UUZ(oY{18lBzxbucot=4QQWJgjKzB;L zE`DM4d-awp;3(b`v9n`du%Da+*q>|z(iJj%Ie_t;!hdk=#j8LBCa(l!hjz_81Vsvw!w-%V`kcN6=cCAxn>ZvRK3`*!8FERgu~Z_~t?>_OxUJJM z&XUZUF1J4%J3=j2YU`HBhQVbj2mQrG*|$bIPtPo}J&WmQo)Ex9>_ztvpyRvrcdP&i zyaeZUH_%6O2=bjbjm5_=*b$^bjldu(f;;fJ=J|Nmor4uz-xbREWJiQ7i}lA6x&emS z^u8#z?t0vzBsOma>~wcA7Iv4C+22rp>~BNXQ5h-@zL!iu8R`F#4D4;Y_)_#lJ-M~OC@o)AOTPM1{|WX*+=^5Q4~UeZd& zLzZ9zM_-YaJv;02ZSPRP++4-EuJ(7y@A)^OpogETmhMj7UN~L-e$z{Wvuq!J%FkX2 zXK3ZDvDmfEu3h5p!ag$G5>nC*J;E=DoncIpm)xO%o_Hvkgoe2IGm7V(duE3B7PfNW z6^cTUtHNmlQfHnuilX6Ek&V-=n|DY(-z>?r^$a&+qgvFsMAXTvZRVo#?|@ZOozJk0 zCmBMff?O!8SJzYpy?b^#2;eAxA*4Sx!~TRwW4@+-B`0SEC*(&UckW6qIup-Gn!g>8 zrfB)e!k{gr`1hF$^Ao}pnIkPpTgxG(%RZhQX&!4KuKK`RHNQlDFEE!_3uj&vuY~*! z43_H-RvXWGaHwZ~MYMqF4)>92u1(1N&Bb8Ar!o|SEMFbsT0Q=rwa6O=Qum%!_oCx`FbAsLqvY@;LXqV?H2*l=s-?i^!#_LUISt~utnaRO?c2=y4~Z$? zWyJq{?<(>ROG0Qlt@xBq+nv-(Fw~EzSv>PfLI*%qXzH~QXd*94!j3>=8LQ)wq+8&_ zKXCs-`2%4h5Gm6*?T-f${_yN-+(t@DncCX1oa@fq`1tewjtFGaQAHemOvgg?yJ;|< zf|1<6yWkgz#u8PzQzY?Ln~uVIqiwix?+GODaoX4DAHM3pgWiB2?)&aVP3RKGJRcsp z#OC7gf@VhQVKLV}{28cg?z>6rff625?r4)Wrx5mVmhcqS<~*;2rQxs0bmLs34r5QEQC$zXGSv?HCM!+gqX@%c0`;?-qP zBwK6knjE`iVk#6J%ZPI_fRnptsTCDvh-Jr5clu#}JN}4;A@Nrgy128Wb%PY7KvHxP zS7X10H0(GrXrv@1lSR>iQTA3fZ1BgD!mqMn9tI8g7@yLt@+AtgP2eyuAPbrI1kc1i zCD}o;6=@I<&PscfdyGUirx+e@%&Ikg;*~5ZIm2U zeZA=k4@zkk)T<@tche?{r7TWZR!AxMat9&uH@pSK{kVesOAypIU%5Gta;vdqu2>Pi z3Oa}o3Ev-Y+{BvV55kHNm1H5#-S6t!TcS^bQ=zZ9seT-HRB-w=-;)0 zFB-P%sqf=`_I!{f%E*X9ESnX_UQlfD&u?>Xmbs^P+gt3bP z;nL|yA%d+QMK`jPuQp4sBknZ;MWogT-w7Jnb6Y)?Q(91lv)s2^r+lZsTRtA1PaS}! z*3+3H=s00fAR5MJRB~cyei5g=I+2H|L-*jZ2TJmJPtWKOuHKV{l{4Eig$l07g^Atk zbaRk0I@_(G6{p$nm&LBW<+O@(dX*G(4&lyI1i_ZdO)4n03`;j%AtN zHFv~#T82$AX}086=`;)CmQ_}EN9el8be3D!mFF!_7if{`?~4z*WjARB8MEnkY@&rT zfr#nv@cxR8FX;*?QU}ITu!z1#?QAELg@DVj%LR9(2-#eRhy`tJH|-#WErT5?Pg zT5>hgG2uA>4{P5Po_oJ!nVn?s*tTukc6Myrwr$(C?d;gLZQIG@>po}t^m(4?={eI^ z@5OuhUsb=VRaI+A>%^#S>_c_6`|8k1aEb{7idhXBuJ?JOv003w_Ew^1jV$-tqtVb# z(k`;~OZU-Iv=QiI%+Wj5Q0x&E=`F|8g>&|eOEus@RRK0TeUvez(tyz|Orcl-c z;=jfipDP0Idv64^YR48iqQ9aQ!db@kOoIGYXcnRi6Jx6Db5J9i8h#>8*3l*d)eWc+ z#8%-80LVuip@JQ>StB7B_}PPu$HrVHsewN~QX|ZE#@%NEL4@j(&>Nu5>C54F#-!W3 z|K>q$m>YWS-TUKf<`>*yh{qgBrbQ3XEH~e1emkROh@KnG&yQRarc#6S5Ym+^Mkb*d zV!f|1LK7pM=+XVsaqdj*#)oW3aiR~vjxRAayK*0N$~z3VF5raUU$;4D_&7Rhgvlnz zTKEqToz^sP%EW0gX$=s&_)7unBQEocD&!`VfoQeMs^egnmUOP)xscZz)SBJVO~!i* z#?s-&hdRo&z_TqPJOBNksyw0c*4@9X!C$^lpostLkWe)>v@rNvILNO_Bm73xEPhJr z;cq2FX$@(R3@j@lRc@89)B!BbyV3Qjg@n#DVu!tvc?Z;HiiKyofkWUKZFw3uumH%V zIXdsGUs8Lso4n%L@&;`2Um(SD);H-DMFd;dKjX%M(c6!*JI8B}#z%$F=L|v>#!uOH zkK2>CkXqWIGg{7s(x;Aa_1*T(yDA6#VC$nac#MGg-UmPE{KjB{igAkZ)3o zuyoYGWz0olG8g}ojXn+md`L2qjY5C_9`c6*y#^vcy0{2%-YTl>=K0dPU`w=t>`-OL zm*%fc;+DbZko-nBg8bnA@LBjMgA8D%71y>BIY)I1b9XHstALr`0Aks^xdXK_K(V`f z--VV)z$&!lR+elO&4(r{j8h}b%$;AE$k0q$+ia;<;vk&PV0SJDYOE|cBzXYuysu0@ z{(^XRK`{^-E^?f4P3#a0gJ?V3*MHs*Iv{xNjydaNVz2%qbA$?rTG-7K<#bC(f`xV5 zU~0NWy+EJqk%8xoNnpdhgy`3=7;KtezA*A_h0_*grKi7$o$MHC6H$@O!5$6AneBv( zmzPLuJom^75Z$y{Xjq<1nN2l)1m0124zLkw_QSQrZ<;4DAhY(kj50Si&5&q?&rKXm zhHQttcEJ8g{{Gji=0wB>q38ugZ#GwI43AXO2{tJgh{^Hx^49;Yn%d_GQal(k+)Q$ol+ddTc9ZZE0`wF@f=P*HJ+jg6ylSz zP2f2AZn3$yJW;}ZKpZ2farJ$mW^Tutko$L`_zQ=77BJ*BKnq{<1RPz4rj=KJ3(vb* zJbz=(WC%9MGBP5v{R8DcKR#K)W=)6RQ-##;Xk-09N1DF1rKPo%nLUlAwSl9BA&u0( z{rrQyaH5>13<4h_*Iad@BSa%PvfvLmi>2tuK^91uz!V)NeaeeBhtxkY7n4TDNrK*q z#D1YLp8(zoHeJcF{-b|bV1Shob&MZE!iFdP_=iF8YT zxsT#SvljIC?XjazeW9;}@d3e2>O-yLlB_mS(FnD+$om%a-*zxbs|3?4qD8x!bZFro zOOtdB1V{+R(&J>@QcB~#^N=(&>X_vtf`!3pX6{1xz0H$QdWm50vQu`32`?#dv!_Tc z@r$0iL67um8=Eg@*CmV2EVHO3_|XIAresZ@D=*_w&nCJPA_xrJMwO~V1UQ-%bREy$ zXpj=gkQZf?@FMuRUrUWFXXd(_Uq~HZiQR@rX>`#rg55Epv899HorKYwLTC^zLF}T` zLPQ!OYi4=&Yom5p1=uXZO=R@*@_1WdUA{kMqJD#CVdrCVa`O?f@;!tLw2C?TG6OW1 zyfN=g!7XBqIuB3EBZC&PDrDNz%qy`s3}jLI$8o4aC-rddNTCJnTPia>hs_@GoS9L# z9_M_R_K`96Z9oK%9R(-TU}`yNK6(8^mi|l0kTtn~T=u(g3IC?}*#6(K^Ow=xzbEd@ zf2-7CJ=0lj)7vc5g5U|^t>}VboKsvd4c$Y{m78g_u+a>Dsjh~7L2AKn>aXM zTdFTH#4NzP?_0A$48ys z16yUTuK6~Oy`kcGkVQ}U=BuMpHo`Hs7rWqMFKIeaD ztd)wbFLH}ItUvUJzV4S&3`0#=2K3k;>PJXU{!ra79;E`lg@mdL#|ru4G4+Je@`UTk zHaAK=+PJtw!k5UCN|SS+b|=EgejnIC@pI<^qT!J1R)kk8o?X%zf=nPWNGO)r9>9TL zoo&F#vGL(@8S(Ap-DMtOw5}Qi?ZPCMdNC7O}}C2`^Zo)$vNEi4~+~ z`oO624Cpzu`K)L(o0+N_8LAZn;o0Mqn>mIe1H}PJ&W5TUzImA2fM>Uaef9;Dv7f-2 zZ;(_kM8aOILRwidTZ$#_-v6-6{TECJ6s0aVzTp}Co#y!dHJE<$NKU2(f4@=7lpPZn zpo8U-H?LOW>q+#^!SFw$6yhr()q3|~#G-E9Hxjo}3(MXuZn*|}C#Abtuxhi#m7Gjv zU?6e*a`6PR3GD-aLmCXo51PvyN6s?G*x-cInk0tDSQx3l+bmh6l=@PXQ-+7Hj>|%n zc11u}EI#JH>jRcPJ-Jb`KKt6#Dav|yVUA3!il2ULRgx@~vQDGz(o)SLA<3<_iLs>$ zH+dO!CC;!4!^xxEh}aWClb-%se&X=6>F~PwXfRCgJ~5E`a7Bj$1xm=l(*@~^aAqKP zO^`{v0y_5u{LjyWUVDc%6D$CL+jkZAU!3&)^Yb8QXzOTd_czyw#&6X`g(b(&XhsHW zMmIoC(LX*t`hS`j<6u$s_jKt1AqeZ$^ypl$#ANiYO@zlIR5Avo%!*Hv9316r)JaVB zm9A@?|Gg&(IO4Ney#CsJ#BhEZQ5V99=$*D z96{53?VlL`pp11uV!t_hedY&sx2*#Ic+Lx?3EXz(>9W|Nzyschu0GwPxxYz%eWvjA zkiyZ1`Q4`-y!@IDtJSk*wzc&$b|K3;payZP;ra>r6E8rO6{Vl&^iBQMg()D_MXK1l z9sMi7yUAv=_Y6<)hKBqtDDWzv2DV!DS=rNjsrQM$WXSyW*$b8jbT=699ph88`%A#M z1HIq7jP47m-&_3|r}5C+|Cy(8M}+TvxmU*T*;E#`*AC88K~|jnVP}u<280L}u^b(P z&_qm8mY-3&Ou(kUsUS#rBq2sJ(R7|NSrr~ymtgYb+99!Y0nBkVEjKzfX?%7C=`{uy z8)`R&8Xaucg=ul*JZC(&kzRd(8fH|(b82oxSwTXfYQFa6+xTR9kzezUT%zjGj@5XC zDQO;}=pe&_K6drQz zZmljAXhe&ILZy)`{=ynfi_0$YOJxvjw+o5RvWKGn&fr_ z=zI#2-S20-sr>=`23auuXOEzlwX|%aM1gxdLvV)HYL|!(lu>4rfOPbB7{pm_)V2xf!Pv}8Q;aj5 zkA{JZOrNx`wPw-MObE%`WKyoL6-m41#cW8)mJ_i{*Ykzr>#cjd!`H4|<)y_kAB&eDM9dl4^lg5!I@p@tUzI$Odd35d(BTSgCOYk>Tzc#y;! zMX()W)>%|hrpH*+WK>n(iN~(&38l8S92fIIX3}^=g-lu?6;}X9-No zQYVtdF}N5}w}QCML%}7*O<>-iZ2Qu&CH;Nw>v}<_k%YA^k5dd{e7{pa{fO8l%`$D$ z!XGEn`=pi+kcRcrX`hXV;~M?~p%y&4T%LgLA?pU!gBk=%3;C`@9Pb)AMn5zCrHIpqx(})&`?E26*Jx{vSJ60V19>9 zlN`g*ZX7|B(dYkjHuaLW@AuUqUGd(t`pW)PQ1qB%vUAr4FT^M;xt~qg8IWAKGw3O2 zu?3SyyeQK8uEzebOk0lxZza7j?hzGh{?dv5<*|WabCG;-YWlBCi_aPzb+rAx3u}7T zC^i(026}yIb9Opjm}eLh+aZCG{B2v{+Ep9wqF(7n}ceH*OC#8nkzuI1XO${T5pck$S>`|k2jB)M0U(Zrvq>-LG&7e&jd z%nh+rrzxy0T2)t7d|k31pk^BO?ho@)8Jn{%aL{Sd%vN2rSL(EwX^E)v-qr#am8jL` z@mn5e5%P3C+XP?JJQ&aR=}Up2x5(^6$$)eAj5Z|Z-j91arPL%ivoY zIdNpz;r21YOYOIa(!ChfH93eUZ;ytZ8S+ zp@nfZKvVL1(IFhw%CPJLJ*8gPmy}sInxr{P*<#@!ykjt8S+{m5bm@eV-6P+$j_15; zm#pS4mFiHk-J!0yE|B)X8J_QwGG08mhT21>4nJ!t7ERU3-~9xZTdN$`bRO?+DK-MY z&>w(;$G$&n=DcZ40;e+OR>tef36N=7$zr`xXUanH!?4lPGBaJhxxq3Q$6TT%_609{ z1V;&=DOoWyDOnY51%Bd=Is@2*5+Zrgf|+mdoOCEG>UJD-+AtK+JoVc<6dsl4$+v$y zC*DYPUV~@mTQ1aWz9M$2MRU&qMKG0IsUtGIAiaAKSw&>aiQ1E6r&F{oQ<3K}E1ONF zLXv+(!<>aJav*jj&s`Gk)Mz>orD1psOCeS{(sIQjD9d#ls}(ZQTdFfqO1bWy{bb5m z(k)G?gj~2fa=~BVWv1>d$?jUist0L3c`fU=KQN0Vz)4(|W2qoD%gqH<{~9U8m!?>y z4Y6SL=ef{(B@;>mfcl}Ag==YOsoCuu{b^9lw-d(`8PI$*&Dr1t^!>S%fjXGIwx4%FMCrCRJOQz16n>pt=K$0H{@w}Jis z(DCFY-Pp^sB{0v>pngb?pixmAX|VDkGBGe9PS+j5FKEruKr;p4OO#sFrT3RDJ%H`5 z9}O{RfBAP;Qz^zcZk`9^4n0WF%9h&MGZ+ zIRxgwxr)C00c|e{Ef;cCBv;@GK?z4tPFdDx0o~4rN7bMLceC9MvVty|SuLcp4hHhB z5@Sw$r{?)e6wBc2`l=fhC$`_37b@?-sm4y0fFZi5X zu~J%6+mx}|DQ~xFsX0)>3jp^q+dh&P2&+?8)7zw8XjfVg-5zNbXJl%-j6O0KJlGWW zASTwXIcjot|2o5ansY|<=^*ipXLc`=mjzqUY75OS2f|aPu!D2IGyL5YW3~{hFb`Na za>kzy{bBi>L(*S@#Z>DX4)DqYo}F8qI(wj2(9KTB65FMUM#%i#!Leid)`R{S@?r^If^%jCb zv)@iGDt_$gxmly-Hf7bE;!ZQeo2Y{}S|+Rtw6=p*{SZGyOZC4$cfY|n|G@2hTYG=Q zdgsRO9lF8G7=X*@>w6}~?kRr`2|d9Q>=RbIKTEjztshdkWe^_QWBq$o=44?0238%! zHGw+-COsvKCU4sV?&s0OkJ6k>oW3i&O7X|r)tx~!^XE!XFykSW#B{v5uc7rT z{lOx%%Z^=ezIW`-9`hfTFF-I%#U?T#`qkzg{BT?KUD0H)y-R7R&*asaQH2C8mu!@g zZ$#K3&wXP-wjaOeYaD^pMQkcwTq$|NULvIeZ8nEV&7Kbf_VRBmyr9SSl={&J!(3#w zDfSd&w01S4m@QZO<7r>{)OH{$%Alh9roJH#yk2#C|8kyQjpn4T^Ee!h2x= zJgSGBJv#m~wTJKwSU9y4{!HH$RSgTR&0uwvFYt!iD*_4?KKpj_`xl2O)*I?H3<9Zx zGaYF)O5bN2m`tGQ2cCLj(St}pMs!o=Kz_p?83^ruI%>NTBrYj0C}Qzlm|7Gp7rFQ_lQS~UHHCa3HYw<# zEbaC7u)|L*x`a$j55XGqFQz(L zXQ7pH_jO_kIIbUZ=#_ULZ&-&6W5TC)VH}^Z&6Zdb$0u0qyYsF-P+=IRzf>{Sa)~nn zZ0U)+C4zcIIy_n8A8@*N`x8A=R}DR-1awUW+yTYSMVDL@9~-s236;zQ1MLpI5&DP} zf)5pYP3Dpk0wxPsop?HvC-?sf$W(!2`VAQ^y@f zm1Nrsm=)Fpd+>tJu#V&OT|^}y;3@)GV?rLCK#`zDBDo`dLcT@h<_WQ=?ZXJJ43$q0 zcq2ce5j)uyg+i8~T$ZAoPQbRw=Eg&XVMqD6znP@XeMUlL)w{E zjb>l6OG3l)mQhe?SIWlBHifl>Wz{78NU6&%5rkz#gsqM15$wwwXno`P#6NRIPV-7V zlVnDL;8iwhtai%Bw@M|sPKSdk1Z?@n?|@IZxM0h(@^!pWBVNmtvI3(#7RV)dH{HQ; z;!;!Y5FNdh=06uNktHVv{KUcwlSfO1t>vtV`v3?=SxLG&h09@ed|xPW#K3v9iq&oYT8QQLW&XB~NyAfyP3Gaifa z&;cC5)zTw&B0@=t1Xw8EnSSuh=39#welY>>h@G0kxJmxP`41Z6FA688T#~lvn`w0W z-umJA?^8H`qapYmO)dU6c~hC7{ufa_^d&EzoFo)mj+{uYwdz-q0}3}SI1lV6UZJ#a z*`B!_cOkt2Vfw6)mJnmI>mTh!x|g~FKGOs^K%B|o{+O|qF?RlPb2r8Uz@Q?E7s?@a zucJmCq;WZFDBNcO4z@mLqurMg1OoZN{bVsmW;fLw_~!IL2BfZktPWR&lVT;ym>J_t z@Jbg{VBK~QS8_v-W<>|7D9GmE(sO%mR%z6G+wUwD2N{0qsBAnB|hjg%^T7(ng`611l(=@h_BoO)v4aN zOr&Zr#*M5XvhUWS2`c~h_#}+@h`-m9WN~os43}%l#wq5yvFkddi@+3Y(}Zu8#UJyY z-ERAYPHx96M3M0_I)f;Vbn>o?khl{>%HM@1B+{^uNY%LfQ@c}^u23Lflsyd&vvgtM z?60tSiwo($SQ*Xv+KJ1BwwWq|qaCt7b1Fo(=~* zAAv1Gx|>QNvBMRiElc7|XIi%)S^> zHFV?(2o{Mt=9W5jB=Ao0VQ@XnrNNqnbK0>kJZy>8@;j%9dYN`r1Wo`KA=$Et-o?wQ z!)Gy>MYBc=Z;W=sEJf0sr7{_U6^YV@IQxX__h@VEz@hJ}KmSvWWjf&T>`3}c? zZYB3RIXQwppCCB*95xE%e1jHs-bR|f-$(a0gTzOP|H z=K_T#9&}SAzOO`MB~eeY8r#5i%qvKxo1h89(rKYxm|z~FqaBp441HNm63Q4UT2NY$ zcCDSxN!wP)drw7s8@HPnlT(aF5jW5pqJ%!SZ%Ki8{>ZP^q^!(Lqbmjh*wLm9hoy!Z;&$o~j zpI633?ux=l&xw0BXBJJaal7|`Q1d!Vm+^W_x1NvrN*nBIz!U$$e_iboV0{l{4}|Ke zh#Or2IYvOSFMAIhFMuY!c?kZXZR3>{k8(G0#g@xM%1V;aI|rxp#Qr=4TH|lr>KQe( zPmyqU4Ua&Y{SQ?5UqJfy_w+aU&Y^tp004^r^FaD{)O0GVJ7Xv#eGaxo5Jp=JG}G6L z%@H%!oeM7KLJeEZE=H*rI%TMZ;+g)zl0a~W7u%Z@9Rw>3gm*hova*!VVdNbzNJ&(L4N$Sw83y3iI8-}L#sKc?psf#DIla$Jt!%2o@$NuE;z0azQ7Z{SHNhK z+T^9TAc^XfyCs`2m&)7>O}Z#NsqkoyMC8GhYm7_m5>7tf=vB~ck(HQG@l`*~GtbCv znDUSftKxnn@1bXAZ?yw?%Iqce`T5?KOA|GxB4ccwQqA5(*_fkkV9toz_%M3S)>+%5s)LBT2^{+7!(Vul^gJmhq6)^~sQ~yYCUu60F&f>~ z)0>W^QXQo6gi=JUgaSrw&$eD0I|1^NbR3=2AEYYXpSC(SyR^|daFi>pQoipHty9+e zlR;TAQJCr&BG4CIq5vHEW{kkK6PAZD7PDp5OW9A>Jm*bKvGhQ=ZO0+9?@?m7;wjcb z)0Kdf*@VN0(_jWw>S1&?+}`oX`3+t14kPuA(OrpOz>Tl>5Qg3_z$ZL@9CS)m7e3DE z2y3>Bt&&y(Wz`OI!{UKExCfM1BM!QZIazu(It;ql#f+*)Cu>hdhmqE|Txk`7X<0 z8u*B$()b?j3s1;})&huGXApHUkH$RebF+{#wbp?~^z_XH_wQ@9X1UTtvVMdMBX}^# zqWXi9@gHe@)@xSmH!DrHVQ~Ug7?G%cgNrb-*1+xnsuA^FMJ%^B%_(Rng_JWk}# zgxrPOv{A#)MSj*hYkAL6epkCben&Tc5hzF*JreX?#oKSVmrnQO%Xne=&kYecq%NwW zuXtLqHTF={WP25UI6Fh&UVirU$Vl&qJo4A}9rzBS(R&CC)`caO1HXNzj|K{-q%w!RsBK&>pP1*Jqg-41}?4h^-F zGYxgBmZXS1c>ER*GURvCHkW!hL$jDwm1phFZjla)RNyt&`qk*!i!=^yr{3V+n9%8~ zLzbyKMVf)hY@ZgZ-PM3@$@1~^7hs+ibfea});}m8naC1e=S8TS3>AXBg8dpZv zO2Q|%j79Es8SB^^7`rtfoYt>I$frBZSDRQ&7#k}{nz#et52gVwtvsxIw}E(HtZJ7X z8%9EGHba@sgJ)RSD9s>BD*mX%Y1b|{1ux@UA`z+qP0_$7R$Py}1inYxM%*>Nm_uwp zSCm{AWVn!rgz1M<`i5kz254sxZh@cM4Mod(Dgy%3qb-_~ZuCb`2&8gQ;4^fQ4z36F zhQByycKV1c!hnrvwvDEIoNMgCSh9tl84IMZdbfAqzQQavQ(AqBq-n+uCm~E)>0;ChhP11clHaCU~72ct;y1zD`MD$4i~ju@o-Lu`U4k+oaz(S6zaJa==R zjR(^^kb1uUX^V6r0H{mjyG4@yt`XJ#g{NK6&`8(O!a>o_LcrR}%259=9r14s08=|x z0bL7yM+;pC>%U2~HpXvBe|J!W-M+m|=DBj8Awmb)I_il(X*zyLLFxdKrKyT44dSChl-c)H;W-!e?4Rz&7f9taIIdh&gKS+ek)cgMr$>~T)lojS z>?$Xfvl8S!v60JnL>?!qHXNTe6KuQqIa8|;=Kl8XGt`xo*?*Uh8`Arc(sfZN?t+Dd zHO!UU$#fG|OujM`77^4dGwiW6L$2&4j!e)g`F>hNr+8bxU3wO3);H{uE83B19LX?j zH<7{3HD!qUB~S0a79n>LJ~WG2{7BP;3|SrmCz+y~pgY)$1hcjoB$qd_K(HYV1V?-p z+;!|gmEc|dHa|L_x6&osPb&`Hfsb6?E_p5!hKisin58r2~G=mu;?Bmh0`6W9Gy(R zhQ*+ZFXnF_@eknEk>2!X)Mvl0qk~Tb)~(ZcoLHXxs26wp3oeRt|o3L+FFk&jR(L3PFHS z|HkzFH>Uaj1x){~qp^0h)BoEpLZSSa)%Q&RS3IjU!n*RYKQbxRRKI5nRWy`htVy7P z0xu&Ygj2i$BC#E3;)P(|R!^{xU_ieg%yvGk^B|d}=GFD?WM-=UCD)V5``gr%Hb7I2 z<{)Yr5#sN;o&{aSU?!}^@MY3o3cYw;a`@bRFM)tqg`S%pZXovw+OA?h(nG%WZ7*%a z7>|e^=%3c%F(JX4+}l|So3U)JleBQ5N<0ZSN1h9N^g1PksM#P`SDN({YIM1`z<3sR zNFmD{-0V5}_EXjk;}-OeK3+X7WQL0%#%4 zA6oJOI4*N2YE5RbL>UpeAIH;SJR>2xPqKkn)y2|cVUd!-|#-#+i`LV%?W*24QbHF9V5gBYiT1~UW$F)xOr{|yRQ}`R5 zj7jVXOp}^aByw6}TnqO?ju>qL{;n2mDg6olrV5xELlOR}SckH@%P-k4Vy148=$GSu zZLVRrjC7pZl}t7KQ;v}P=oXZD5#|XT_we?pB0}K>9eIvvi3MqnP7RZ(_UWv5Equ1V zPTC>nb8Y9J0QSnk!>#55`x_5GS&)Jxbu)vKMGFU#MGps3MM!GIbLbEO8hL7={LxAilr3AaZ?7^z zmeATMPSSv=jrs~kME)5v@i6ow&bBoE7KI~M3?okrBY})B`ou4MMHU=VR>pBS==1sC zM-4#0-*>J6pa6e$TC6TyrC#4HyZ85ArTG6RbpPI~|Gg=nknZJ0&G=d1M@kxo?-m@6 zF$GHv2nNOzL>@{)Whju8Kus2yL$iH{3PYUs4DfBpV$SFPs}t6JdBd8SVe8!EWbN&a z!bcv{d^yrjm&OlP4*ih{leQmyBK*v)UZGN9j3`J?ij9j~)_JxLa+8I4aM)pg`k)9M zGGPN}M$_2>jN4&e&?&I*%&W4zRzHkWU|vqxS&44l*gOlk8M1xIaVge`=1U!DV=E$x z=oX^DsF+5QC0l(($<-_@mm-mCHfGUg*oJ|{7$RA_sqAaUu~SEFHpwa$FJ+<;jo-LT zqP5?A7CG`JhadyuYGB`buvD~Klx8$zs!^un6EaYdav-MXH>9o!WT9dJw-gL(|c_OJKOUG}dIUk^{;a_Fo+G(f0*EfJY1F*6Y(08GU$SB%z^*N2qW zn=#i#5zRKzgRUASg^evub#-!m7;xk$QnsB5Aq^3@jGG#Wv9WN6{2l>H$=}a69z#9BGy1gWt+xZHCf>ZfMH@eL>h`4jKy%B#H#p zt~$rjbkETzMVC%=^9>Es^q^cyYWm9w^HP?i*_pHFwvMAYsXDXbv8ss?b1kf7Epu&s zv@s3ml9c9}Gf)DN6W<0%@pTUw7!s;06^4_ngc3(kR7v%fs$7*TwS3l`Mh6!O%yJo= zx$J5r{uU}`ZMeEED{=dWdO>DJdiqtB>8XR^k=&1qRLS2j zG)~sySB}4_c#XYTeA>LI|8wcu*DpRN;WznS&(n)+kH~Wi;dCV`NZB^K6)kTMNsAaJ z4=x2-+UP9bLW{|YDis%98YKm3OP~yywmvv_-w}A%Hmx*wsb1^o20tsBTXukBkZfoi z-4**xH6pl|fGInjMo;hI8!dd1gsJE+K>v;6DH$gclGl)}+?|^{|Gv)9PeGgw5qBIl zJc-G9L&jv<1ID#N@>mnshFR@{isZAiOAs~m33;O7xb8S}spBH|<85{(AFD;TURLhp zx!Gt?#^1VC!Q_eZSSBrM4|(Bgiekf-{Ev?Kd|{{njSsJuD7!96Z!{ky?zhRGYjBv zga3erTL<;s5RStFZc1!;oVx<}U@htk^bAjNxq_XbtA4^~A11%T%KbvGYs3(NBdN&D zGUmo4kZZxALHRf)QHAm>G{G>}_G@Sf3Wm0x!upwcn+4x?9Y&Jek?B!>{^kNlwQPJe z?1eRQxaRN65p$Ju88S^8kmGU3Rj@ty^BE&h9qTge@`Q07a(1k5QM>K}vcly47Tw8h9ZsWAnc@&uu4 z^YLL>u4V2mrl9BA*WE)tQKDQu&7l$5LGV(mw_8ui0s-KBz~l z2y{@1%^QnHPlLIWj2d-Kot72zmPOmv7qv4RvyMnN5_39h_SSnjd#hP0{{h8!v*oct;G}{UZn=gMjG2O- z0Qk#@A>v`CBqT{@H~+2AdwN~0XA~giWnFfJbjEe;E030kQLlm=J?f;H3%`^3_%qmu z>dd%7_vOPZ=<1d>C%Nnjtav7#HOYFtRg)U~aEmKfz0I0m(@C&==ys0< zSXOE(zgN+6EH^Zq?o6&g6@O2dQ%5C7v#l)d^Hh zUup?<*BZs+N5L!Cykfp=^mhv)7;&`cpcS<|aM0=QqETBvDKn6QXk@;KbMK$SBNg&J z1rPp%KU5?*8vqU3STEa^Ij21SkhmIPbeV=Oj#0^tXp z^B{P`JU1qF&L(I`IpZ}{NxQ@yzsCBu66n3AaN(OUo`=o@U&QWye?8`gs2?WCwMVINdhRXqcUFC1wa1 zwqkHNJk}eGWLO!GBBptEE^~9CQ>2c8&m*2NpZrYdnIsdwxHZNTyb^XYKzm%6zn*hq zE*8gz8bSIlm7ft|;-J{j#5(YIh@oCLUR)@bYyZlgvUe@Xk5etd`2GvZy8aEHD74in zJQTrusLTYR1V;7&CO&#J^@I*1TA>vf0$6g{V& zuWxYRN(>2niS!`oC#m^c7Jn|||M^y!N^Yu2@;fiIe;1u1|3Y4n)wQ!XH27wC9KN;T z6kKio-WDrNStE!beiAn=Mb(Q*{vowmy~VHqG4^e0=;uvm|A7gQK-N=o-%u+uNqDAd z?i^`Coe@Kxt2G)5u`3&DPJu*#6siyN{<~qTV#3U+C>wjlJQmXcQMW*xU-qsEFuGnMy?1b7fV3qzb`{kf3fXOU9Vg?iJ$velRx zjORhqC?MGha|iJe;GpY4*>xT-^OvqcE;Vemi`1@U6{+%K+lADL^>Vs&z&Vo(ReJKC z+cqNfm!hxW(BnlDFXg=xu+i)EhAbP-c!6BnhDB3%2%o{01nCv1S1hJRkKtDdX7-ecp0ATg<@@&b@ zPlROK0YRiO;wrs?esVK6*NJ{cJ7R7DX`P*TMO}zaT~AAUb!L7uxYh*YN|B91r?-dj z1IGy&$dkaG4Z1Evkn$`VfPE8x_T9#Q0Z5~Lg5}PxEi{f0r zOC#FhvBPo!2ou&>OH03+L#|2ICctke z`afB-XN9&=_ckH9i$DCLE5cag?l)<;55m=v8dtn+kI;m@(lW!iggm&j!k=PXe6YCC zxd@d(qSC7|??N^7$QSyKffVdQA&pJl%nPvxC(%{+@T3#vDcxMemM~q>v_M>D*R_{7G(j2pMOrPV?tOCxfRI(@jH!rqA;MO4!C7 zWep(097KHl$?W2?nm^ z5M&!=AcMAz62U2aW9`vI4nkF1gxfsOBCJSanqt6L4IOgsqx=1if#BUmtS2~W=TNf( zgUSnm7)&hFmEFP0=*k?%{=)O0c>tJD>^-9IfTjEP#4`LB0#@GI$l<>j-xJE~|2573 z*1RyZGqn0U%Qc|%Z#yoZMa_kUA^5mRttBOftra28HKeEnzXVI;wwcy08Z726<1Uf} zv)?JYUIV~H@k4JW`f&_78Pv&>XZ>QIr|l=RQeP&Wsq5FWySu!AX#L*c7tO%=~UQZcZ33N78XB`(BO>8q{K z{qi26LyK~iKz43Cx|`dFF1W`x2CY7JWvFa#s=s^IARmHCeheIx8goE^#MxzNieCVK zbZ5w3VybO4VLhxXCn`i=!|*U3H<=Nc<*)CgC zsqy=cyn>43F)Z~kDyf0tGQo=ScT~OI2*gc6$7VA{UP&Iv$h3TM$h?fWR?+yhW;-F| z1;?FNb4TKv;6(hMqbMOLdj?~D(q$4R|J$>+x^{MDN@NpdGS|+@1y$}$$>Dha8_dQ% zI#hN+`Ft}Av|??n%7oITF-2gdod81nEXtlDSr4BZlGrNI&^C92+HVo=IOO zX;dy-*d8mKP&h2f47v~?0;DFBKY7bo4Erk}eFQe`@S{9_vpc^ed5WHkdw+9!ZoTju zY2fo#$LTvGYdc8Mt#sDgP+>6~=Q32aSN6{>kvG73GsQ$@UjPmVFGsZ?t=Ayt8E0l* zduaw4rEpaDQuWcapzMZhFH4hPnBw7A!71<)D@R=9RRDRAr5*X;#T{jRUq|416&tLc zsap+@kvY&MNqHFr9BSMv;dlEd1Z&@t^ECL<6n@@OyI_)vAAZx$qzphjum5hC0wK{v@KFgmiQcp0&X9t~H_?0BCy8hu0o-v7kp5R*d>HhgbJ03!cun-Tw) zIQ@4*XF$c&9b*B>Ybc4ciBSyG*fC=u)G~&Mgglo_rx<#>U#JHnR7{kV3QI!Y-H(w# zm_S#46n;^T|B0x<(7b1wU&3cOMHW<(Uwln_x_erC8m90nGnP1xa-}Le;Lz31G1>mg zb;^CR^C*JnW9khDu;temC@!G7FtZQ(K0556Cq1#}n-wr1rsU7fOvjv9v_~}Kq=ZZ!ns=@@{ zeBa=yf-y%q5n>LXkfLj%q%AjL&=3(Y7-4i`c3Wa(=rG3$zedByPO2-EZE9e#P!nA? zQgImkCKFdfFVA`{t2B1oQ3*scpMfq_Hs~@xJD8V6Zrmxt-xtDdRpPXmcir_f@CiC) z(S^})vzjE{OhL45G_MMdtCLg8sW_x#gNwraY{X=paaT2*WMziCnxmwsb>|+w{}H(d zy_RYN^{Vt2kyVjgku82-qabss&|FgL96}lr7TwS}HxqZyg#Tn5#B0;Ln|mq&rvB;U zX^_>Ecu3%{N5u)eUao|!drW}k_S!Sj()#mbiu}Ma#6k9j7!fv)n znb&i$Oatt;^~c$^#!_%tqI+#@dDER1Bb4%_YYj#86D#%f26uAS)l@o04!3=qin29L zD8IU_$--TlLE)B0NEfhEBp6CCrW-M^%JAQKxtoee5+TbeB9L&#RGBPY33y!9*1J)P{3C_^<<&!kDT&!ymDf0Ja8U9iikd`_HTVSq~+d5>Lp-L(u zUWePd?vQFrMF~M`NFOvc8|7O-tlrM+KiY%l*)lN?>jqihaukAL-@0@%Ruk;poMb6B zp)>klq`hO5rA@XqT2*P=Mx||6+O{)y+O}P3+cqj~+qP}nH{b3)<8=4zhPOO27Zj!Ksp0zimOzL%&}z|qv!ad(|Aj)ps>kg%m08BhaV zBPi`!gFN{O6B3?e&_+ezl2x#(PB7DuAhKe!Km${+&M475{`JPVyokqiq*LMAFe-G? z^yGNPAUQ!GL$-8Bq@hs+1&mc8YlhK^H<`sC9-uNa@?j#sVO9luR#7y;E>b2Bm?K_v z^k9>@;B>}ZYk*j9Nr8ASRc$#xwfi;N2oJ16ZgjUoPUs1Dmz%U)XZo?X(e9@ERqX(w zrv02yyaMwe+a&@yysi%a^`%_;QNBgXZzl!PNZEv+C|u>CNckjaVnzkW2!eL40+O`@ z1R~OfuI&k7w86~qQHUSdDS_TGcA+{D5~ix1y<9ytx)G?RJ-lQyZE^Zj?J!SosP1*V zJcbOh1STY`Jt$-oYWZo-Cvi4*LOndthHL@PK6J4zWzRyQxOOG!$EDO1<(uGfO@rV9 zrM455_JcxILBSX{bq5F2FEM4&DQ85wgj-?d=*#kW<3)%vO5(}tsYAta&DQWAe)m8C zw3pQ~f&02SxsTvtR4k~CCPms2P5a%G?b7?_x71=gS8ae|zadJ8P{v&>>hbMx00(z!8s3HL)~ zdPUD5#$wXX3FEfYLXCRz#m>Ochn9lhdTJKr7sG-4_6qmu<6*ML1K9me0SMn^!=#o1 z$%s9C^Ds62;|L#Z+XgYbL-Y@rtUZ8EmW(kCTay@VBh8;yQ6tCrA+rR=uhr%<1EaJ) zuLlMSTORQzb3dpsC)mI|QY?`?ES$Tel$mm2IKi`%7*E&p{=l(vct4takuj!(6347J zksx=BX*s^F<9MNUU;s}LEuC9Gc>A@OT5M?w)Ov%8*LuTJn%NHC8Gk~Hv^cT68dcv= z%Y2d?24LaG?wF<4B-Y{x!sii^^e z7p=HZh7%3T%hU-`^<9Oi4Ju6rx-Grf_u{ktop*xmH&_C243I+ltXd{-O6y-?FDDW) z9*Kv|&Oik(06fCWn2KnZ9IgB6M>>E-?n?WW0ipmn4STQYX$Wh99~mB?UyKCR$JZy^d>0&=RMt=g0n3C566=< znYKNuTbsUagHQNW1M;96fZ0eY`a`-uH`CI22~ z`zALrU|wOg{djuezxXwz5tsGZ!UvC=Nx4v4 zs%a+q`}6?<2vCDusFB@*sZ?`}r4nj3&Ksi{7wWzswm=tvO}iaR|BQ+8vI6IxBflpF zvj7*&KY^J~!dkum%q8&Gz1%&`VdUvoMf&zDR8aZfg!2w|)>g*jWp}(AT zEn-U>*dAI;Lltw8HPFz!@S5LstV z_Jba7(md#ZijM3UsnxM1agXF))dA9A0MKOiUH4E#JMFJei^(U13Me z$|@+`GQv)ttJ+&U!Bo);iLIYi^_({rukT5ct900+d=P0`54LdE2X8%R zD0Hib`KhlX=?;$=WE)urM=Hk*Gha^yV6*F}_vksd#FT@0yzXKg7CRc`1-?bZ^*boM zyQDmA){6fVAObxp<0*>1Aj1wE^gT6H8FHQ#L=KHZfG$JsXh4jTGISB!)6y9qCl28Y z9g>s4G4D}-3RM;+3^QXuH|BV?j)J9`;~gRR8S+hd>Nl{-f(NGQR>OYh`_e+#W@EbJK#7P@Cr9Qd z?gJ`sk2o{5KCE#jbzuqwyOQ034Vlo9B)OI9c#Aqbht>6S3Z@ebn^Kx7?HSRWoGiIU zb)TK;|EgpPV1CULeKIRg z$mK8`Nn=6_jSJ99PoSbGM=d#w3#mi%E(q9Y%}BT)WBJ|mW`+pPteE2?Dp1 z0QIjn^5@-atoyPJ;upL??f+$cJVwcOypL2>P>UnD1A zp!Z7yqYWxr2#g`#r5t2_l3wKee5&sfqCy=8H=9Rla z6uUrdzZa;3n$*jqmCmvn>H^&MjM=d(Uv8MO&5!M@mlTiRmaZ?aA~j;9@&z)p-Z(2jhuc!@_Nl zYqm*nZBXM5dbq$vQo2+n-}1n1Tn>WS@OO*-Lf!R;CZRn8GOKa5inN7Y)^j8TXu?hc@G9tf+L*+$_0e^N%W`TE{$H43Z4u z^|IrafDvL*3(CaI1+n5uosOVKTsR_MS0ANQ);XzjnG>^-=Q2X*o5#s8)hCOUyqrdY zpe7_qp%<7`jZx)Dkt}jbF$gn8;)B+bvSFRtHMOE!JdgSS1WBFj+fBg^)T9 zZ=u~cgL6N*+`Q2vo0sOf7Vppit?&`DW|03_A35M6OvQ-8HA1J)uh=8uIQB52ah~r9 z>r4)H`O;P>bGB~JPb%oA^Jqm6LY|%LmA4VzA(Kd4m-08d^CHJWK z;ueWgA9PXBh0`Z?PWToTwZMj+nq>?k&oCcpFM)zJXVAes9r_Z!v88SrtN(4~g)+>O z{@Erik${x$B~68iRL9cNl&C~4P#|aQnzUfhgknMj1KT5@`zP5PICZ}{^$BeR5}tPR z#O_X_CJVXsn7SL`Oi3DQ$`Zc7I*R#%@jWmO@-og>eXhVnYi=hf~2Dk0Q#EmKE(FdF9lXK-m7%~%3=tikGdB?sgS=Pcs@$=EYHO+rAh#eb z2_?-gLl3Ilf}-dk+wq1#L-tVXSGiJJK`BTKt=c|~KV^t$F4@8Q3)l}~vN@5&tBO>c z+2yS0fwqYhbxHZ;8;a*w*~R`z@LTB({8wRXZbGbLcN~S6-`Bs3Kky69+P2E|_KR1z zwtwUAR-o_-(UBX_=8@{Jy2e83MB%}XuvdD6?Nqq}Ly_5yqWB;-DGR@Vb}mxjS}Rbi z2B3Hk=per(F>kyfkh$$FTJJ%g=VLu&x zp;>_;!bW_kfYRP9JQ6wJ4rUrFlyp^L&`w{4VX|<3lc+3`X%4v?_$@j*)dG z6ZkWdhit)q4QaAuewCZ?Iz24Y45m}mn%SS0K$s*M$(!hI$RGaTK@+`M{_4GzoRIyl z*b|{hFmOF6gdecjn2X5p${`UonEdEn4$73%Ah#coN0^ol{ny8i1m4PLJh}P|YLOrm z0=}i#rS{1V@HCghve`kxWtxtaQ0V3MAQblCY?0s+{%lRdlxvadj|diAVdPSwti|v> z>RzbbB-T@3s*4pvfE8{9*&?WfU&UklQVD$Cf8@{5TvK+QGD09zdI)|IDWIkrc+t8Y4{j1%Jmxo5Yq%i7~yJ{JmzZ6r@AWp z85-bO{|K2F-5=?~EKOh{=mXC55W@cyG{sR5@-+N-tR*=!ru=E^E+_W85tj3)L^j?K z9e-FtalHGS_!&U}hbfk#IxJQ{I^Qf@)RS@lgh3q%Ea};?ocFVu-wvCSc#xixy-=>? zET7*FfM=v1Ty9k}>z=43>YW4ud>8n`KIG#dB{I*3T{?h-c``kJEwi_+zIK2)qBfns zx<~DlSjkZo_OQwhMX;E0T~a+k-%547P{_1&T`jIdZQ9i63$eZDmF#ITzH*vGOc2J4D>%!w$T4BMY3&tZ2Muc&r6Lcba{U(*`%J6_b|N zl1l^(R$R^L1Q5`W!Kcq!(gR(VzRhvSP6c3Mj_q~S=r<`z=HSLw6%Lg@y$+KJvUk}a zzn1waHpI{2_NSuQh*h6tRakIMJmQE&y(U9+$v48{8)vfe9D-ip_`sP!RiQqMF5+9D zLlbJvo;yV4pjBHm3#XZixz_@^nCmL;wDT3=nyIx8afB!qt)m}guI_UI=oV^9zl+?q zI~0Cf;Kh?(Tb~oNUSrxH6AJB8MsHD3c1;<)5fDifJoa)nXfrUW=WduJOb6MsxZ|rD ztzrPgn6VgBjf32i4S`2f^po?p73Z7Tvab*33Fh9K`_>f-HFYPEK#SsSoMjShn<9^n zuo~0|lJN5_{Rm*Q^WXX{J2Os`p`gB~^Kia>lltF<>i?(s^Y51g^J=b|*!vh>piU`< z7~pD1JN!Ec3Q$nM3bX;q!eVrS{PN({s^%Qa8PQ^iT5A~veC~J~3uWrpr4=ly_0)1e zA*vDc!sc+3nGFv$72M_Rmu6YcP8dc>Li)kpOuwEES~p(bhIXsg9>4kg6!#64dCA$r z{FS(){!4m*xj)@gJm}N_J$BoTy*&q*b*B(NZbvDt_0V z=Pdg24|L;b#^h)Qr-4%up7S3FE zrx#UUQ|PPG*AWXufs6d7-R>hAkHAByzqjT#7%wdFK+i)dNW^35a4^qh?041kl?y}% z%~6N1HRM*~o68Rw$cG|Du8JKD5OrtcS5R&qZ-QXuygNBLARLB+g4<%7^r8=OACue4ogg>pH(l+Zs5og zzdfI~kliv35h>nPJ2x6T61}%%Ks?=-bdd~YVQisYABdq@}+NdX*Gfe9<%q88r%>oRuk2MXGt1 zyrNF;XD<(5T za&n-^WOgeTKbCCz0PJ2AP!XTWGY7s)ae@V_%%ihsg*voK;O6Z;2OYMdwTEoy=%S8f z)RvPFvxd;9zFVT&2LaPF;e1@mh*CSo)9cB#$T!un&@SUBXzx*~<-rO_k7I~k5bo{; z{aMCC$;Nd0u@?gDPz7+rY+0uXC@pGL+5HpOA<@MSY_Xh6dPk>aZAgV3H6?~J*Nz+c zC6K#>XEfK?27s!VMG_<8KTAZY%`X?fV8Esk?};P5L#Rp3aCuCUA+2!joo;f`oxjtS z+`iqdR?Yy8s=H#rIG$kXrT-EQu5Zx23;JqK%fPv0)nh*@t(}&l%bXm!Erx>J1fa(l z6vYg0v&1&fyZSvy9$eR*hP}#Hn*PwM_MuSy6s~COSt>8eT`)&ghrxMjfHpQ!4N-=% zWT?}R2%2Zp>Lm$K@(}5DzUD^RT)YC}D%$@2gy7$u5y!+8g=Zd|8>K$v*rlLg6#r)O z1mPvFquItxKAUCw#I6lL(>WE*n-!$9qe7uQcV+%2+)HZn{5`ns7r9Wc^))99?Y16D z=i*h(&?nfNT(3}*YHt>=1XYF@$NUwahiETIlWf3iEwnd)@iVnVoNxawB$S*kYPaTy zv$gsoUPueeO^3tQk5T!?MU)`cxIFBA7LI_OnT`zYG(pA$J>+t7xmv-#`(h%t)^gf~n|>R&wNg zT+5$cV)J6g0Z?xc(lsaSb38S6hvE^axVU%8`a{84&9L!k81`g(U_x;#WI2p|-jy*g zl`i)B=o1MD+XdYvQFDcY(ID-wQrz0o+Z%+sf^^x_btd(l5xfS)6`;Z|1 zRnrI^CFN7{TJz1G!wyn6UXNvc>H|*Q2~Dc3rKGQTi+r~RgYov!n^nNpVXd^}+XDuN zikVP-gz0s60SR2a@xKMNoeQ{IHUhv(IICNkw`nTEqZy9H*R<8uxGjy@kE%PtKl2f_+1%yJ;cI z5>=G;q8QR zBv?Nq@XB_Lzm0_4s+Z6ya*!}cxNkb#{!che&Q)8eL)88{IP``_fa_AYwt6M>Ap8n3 zSF;_l`h{p67g5Yu!%S*m!+zb^vhoh~SS*WWt7YFH?7}rm)VV;!F4;MT2s^hI%TFj^ zSd9L3xiK68p}5~xDk{H1U8Od%o$);QF6rKw0xYD|bH*0lnv}=Xe`9iAkE2GX=?s5SI9q;Vf^?gs%is`xrw< zNa{Zb6kz~-@7jvYC}3f(`XBJFG`K+`rZ+Ho!TM8;a39&U#gTfxUm}D9KbDKHX4;$V zpWwv>_#B}{)*^^R2CDy%7GDg=JuDCo!zgjrBQ*|QCDLPa&nT8(vBDrzc}+1FKvUNp z7r0RFxAuLEyg(|hnm>=cfR2!xKNmW>v3P!eV%wf9`qb`P>IjZ;p>Kafr0O;dzZ|tC ztTbR~3q`NY>8~nasVb7$(eL6t?#vvL#0Pj0nDdd}LIa#>XWZEy*g2U~WM%@ba;!lwYfGJjiNxp6 z`z%%lfITE%#%>p8*H{-b^g+GuCAuK}m181_g}HP8Myr6?M#s6!-tw2O>O3|pa3SAa zksqXzh>~FUR*0=p;#h;4YcfRKyoa9A`473UaI0ehGX@M}CTx&+1*OZy+jN+BRC;ML zLg|xg1cx5NhUl8(31ol#GWXq)OBp0Z_UfGAq^Wo-x1yHoW`Pb*p zi+yE%-vsXQH>)P^T2=6<$M+D{)6nKfuWwGF|FWV&o8xP%YQ&&Bci*- zf#{KiF3Zlt7tA!?fI%GfZHV}j=Kbil^!frT8Fuwk8KlG|>w|R;df=||`iRr~R0pW+ zw)Z!BJ)d7bo`7v40ij-@-wBvs)Hxdh9^=NA#K*?dO3lfQZiIM}l&RCvu`X4crwbps zLaEF?qW0;b?Byi1LRR$#3a~OZklcig#cy3s4kg*lEbNiw1$4ZXZhFY`E(;gh%z6xO z2~R=kk=;Qw5p6~gXfQG0ysK<=?@-W2OZCz?k6k8Kc44t>30B9)XA-&O>OXzF`XtNK zZ`H1lB3bb>{p8Be1G+EGAbh9z*)muFP?lZhU}AH~t8&g$5iMbv&WI0h>pdU;q~aO) zWzJloLZhg!3N*DtKU8S#a9L5eo>w2%mces>64LdQVI zNJi)Ni3yDHP4NZk)6)fsm4vqVr_TAm=2w=OfW`UcE`Tq0`TsD#zauaIKEDLHQRyG_ z$lOZ6uKqq%wCJcD-4&F1-O=!L-Az+U#!V^lV-BLmL4jF+bD8iA>5#rY5UsVi%*;%C z>(~4DYY5$dQOF6(Cf(wYJ$7vwQvrhB97Yf3Ikq@23ccYe*e^~_BQC4xy4Gg(j?7n8CtR{td-baNVOG`fnj zm^Nw?oGVNdnmj@wXDRBsf)%UXL#Gbq07e)c-fPtsN26}j%BWJ*%d3OEwUC#(kuDo= z2jfK4n)UKR5By^HPHzEjxkG>)k0q)dOqTS84!SVb z(4bU$%Z5`ru@90Cgr3LmE|Pf>)7iw!`o`iSc^yqi#D!O232m+Az90;G zZm~^;l)Bh{D_&Q*I3Q{pi}tMT?g^`RYO!TL^m)Rn=_rm&PpO7MBf`EZ5=J*eAqQGj zF`{A}5V-T_wgxBo-5W{8`ANh{dPscnIn{aPOOngFY^iD&etRF5#=U3uGVJ$BpJOr- zID{UtLJzQlZZYE+SYWg;PT0S715J!qpe1~HXZM#J(tq$!GXryaMp|VlemheGV?&+4 zeI=&VcpU{**&?C z>?nzP=z%D`3^#I`VR}D9Poed})}*c>t3Y~;hbkpH&CZ7#BTwzjf8$-XoO9N9sox&G zqc-;YE1UWf@Eb}O;Nze&_;bm&7KKLX-B%xEn^DR9Fs!U@a?&ESqX zNVl36_d+NlhZaI}w$~iH_GnpsLI#33sG%l*PrOMq>14QmT}nMdW`*7qq5+D?rmqVf zA;t$eQ>R;>BNNw`VV|> z0O`h?)81`jHeRb|C6Clfjc^Lr`e6?=o*VA&r|s6q{DSBVHJ5l1ZIBID zr3HvAiSe=I!A#0q0i$aa%^ksu3?Nn3*z_(SlPEs!fFEg0(?V}(jG5kIA|Mq!g>jpt z=Rie}$9#`H6oLQ8C7r?ZbazYlwxS z_a(n@HC|ujWc2^@IrD$=^1u6dhKjj8mI{WKa%_EKn-d~ugWSr&LQ{-2f>rvD26{)y z+2j@JKbrnX+2tzct~hFx%4L19?caI}kkw6&0|Oc~A@_iu;f;#pa)79_lDAc^B+xVM zov5qM5@<7~&oa3W+j%Z;GwtuPKHuN7zJXpH5=-~USEmaCEB_$1kqU>T097mx2FL|w z2tsTkz=;U4L%>wJC@N~o~s`jUbe(@nvc4Vns`-P r+~mNjznSUY0%aA&Ok( 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

h$j!b)a<{KDY4mj=5BR!~t-kK$5nm6o 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

i0L!1+^e8sOz#`z<8oie9c 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ⅅSCgzcErM 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%0Dh!?v=aR#xtTv&1%A|ikQdAy{BZ~&64(#Lxz~|; zecy@yYqI}Ah=7BQXv?+~k}vgT^%&amqF4?t(rD=>vdAWpCC!nY-&WK9seWIQK1ZY{ z!^m2iBFR6a;L!$|E^zdV_z*YP9Y-k*-B=DneHB(jW+B0qZg@^PLRnkD6Jb4VU$Bp0 z%yd`;HZ6kjdJR{pqcTODIS>Iyn_Ff|$Y-VR#Gy5CHjyKc!C|j|xnt$mobJXq5u7r( z1-90FxG&zWMlL8!_3XTz#KHC70i@U;_1n!En zC!5v^uDr?>hQ}0!Qj&cC152Pluv~*9`iHDNOF8&YN=UuJHOIL~HFCvD8zXzWc&rRF zFJ`XIc&U+$ZVP~c4@xb|tu=kluFS8eX zIha{7+ohT+{XUk-J1j_4pRztTBm8>uxg^V3j;gMjnpSf|S6heI^Z2mK`6U=k1vLgn zZI!N~inf*zo|0oDVydFHs+N+rvbL;IYjyyAuAcakZj<5lWyXFosIi*T-9*NIv5Qq? z$M}RYeI+_wnNe}TilY{mAxHe)j>ODv%zMRhLk8a4N) z6o3KlouQhI@}a$H`r%k|BYtMa1vbbhAoA{<%9toL+jR)#XboQ>Wn9RfGIsEHR$#PN zai4VkjwQ+4NG_~iFx-xKkMLH-nE=^tca5?FH0lL}2-#=H3gJoUS~r>U{L}Go_Sd!f zxDujf+T_PQ^BO0G%-Zr~4+^HW?3sPe_CPfiW!#q6qkyN!rK+5AU=E*&_oT!v74>lG zPTIB>pR@nR@pK=Pp4F5D1&eQ@G+xOw#gB!0kUr-1K?(Sq= zl2V2FL)M2`I|N4P?^u=w`s*Pm3tPfP2S&NflRdY04Q}WjC@m7yj@ig*ip;2d)}*-k zvI3o+hBbu=KVeSlGb$7f;7 zQj=vA)xT9cqtmIr)hE{#V3WVrIep5se zkL$ku3*0qzpqb60IqC-tL_g%-Ut_t1em^w6$PU}hEzlaPJy_cuWv~gM^JcpQr#rf4 zFhGz~j67IzaQ~jiSO1(;ZsIfW-yba{$QO^*&DOnnLdx*5X4lGDy(Q5U;Ln^{m5$_{ z*QR+?1Z@xXl}oHR8ENNNDD=Nd_!fmCv=C?OzlAsuoy+`P!uPw{hP`&Kf9&GJFmw4% zsmo^py2|yw6tZUrDQHH9m756(O?ciLB>J6&EZkz{wI1%BSD`}chjofL0}mzqr&dJ7 zmSxp~-*GJh@VUgN^C@P}n%ufr_2hC6saL!%PgS!C|2s*zWK4JN+gd-6f99Z$Lvt3; z@nk}~)5EcC<2gXyUCnV;RjA96P#3`zM2oPTIcCbPHCvB5TH08`=x@TYib2Tu=ll6p zD%#&BD{ko_N8B&0m#yKAAL4pb(wc_G0~n)mTL*#ldLhj{YvaN*EB$Sqm?>O$-(a0) zrSVw)ZcB+MK_b=8Y-9}jes21*U6=je9YC6ZUX*QTqt`F#pULbbHFWhkz%cWeKM|vQ z{SpLffbxtwOYPd``km*zot%y7+_YyE_<~UL$qbx&U)h9(!q@zA>Qb>CWxn>Id`fHl z`Qqgz`nqEyA_jYAmGOmDBIl;XFNpD`0A2Rb>8eEAoHobu&*~PK8 z{p3%IlO;+zt_khgx=eA~n9^n@)T;{u94gIjP$w_d9TWczZbmn!tvH=U?=yC-=wBVx zVRjmq_h~1V5{G)c_q13%b`1*6PmuUG!{SmYsO$aO%!HMx!38;fH?=+Fg#<`}+~M=f zEcgQ%Chivd&Pcw0_l&>^jOkl;JgEV(DHZ-jM_ z0R}~Ce@wGVdx|*?d=>hcpXf%RpQ?wz&N~q+ms+u{m)w!)OYE_G9T$6=E53XMQ%9Q= zihI#Ku>U&K`|YUs;_J%&g3V9~ds6i(cO{biO^mMKV+|W6 zPw9`X^=w8?3LaRI=PylYMJ`wuYJ>ndyC9b}D3VA3bX^jPh>-C{yLJ$XMn5SUzMiLH$j=V zuovJm)i^~*fL~x#ptF5hTR-ASjHEcU6PKeEpdx4U2z-!4u9{AFEIr8QG1abUx28b% z2~5*UEf|pa;Wn;yj9a&~jqAGLF*Bx%5C%EVCn?Zze|<;6jq4xMPG>LgP?yQn)w7n# z{CZbXped_aUX(ARUos0Ugeh4mk-G>P*tl=VYO*v+tC_&!ItEZ2Bf6O%x4EX8RQ{k? zsMBVQ!cd(H(z5EWS_5ln1*5nN5{^;NDpJpSOr!x+qOof;=~Smp(=1JmHIQgbDbZXu z8OLffos6ot*&0z&%Z|BHgc#LON2zHQOe8+2_WonGzoMG@M#U~bW|z5c`G078r})ak zZQD1t?Nn^rwrx8VJC&qj+qP{xGq!Ep6;_gyb?#p4ti7M^-TU0f`5TX;e|@$-zSjSZ zg~!&sbnCJyGy7ac_=oH$JfMqAcPvtMQ@hDLa`{sCB0#xd@2_y_#u|93Vlyq=QIROM zhqSgC7KQ`hN>*odiN36WY6)La1i+?OSJslNxsE8sM~47Nuq4#Y z8_|#tkXiPzrGar6GH?2q*FnAuVJ++`$%Y!3_M%FI<=6gpj%QpasxY4b-=xHQupK_WznB+sc+WcfxBi z;5*_6+BjsHMN(oMU)I-djExaVPK&JLkkf{75}A36=7^aR&ZkM=Q78Nthh}J^O|UCk zZJ*>ZT){E>B_xUSXC8}ew6Rs5lcPXR;7I}mH7eq+rz&clmd)@(Ir*NDBaB^f1_U7# zhrS>iZpnec8U0Cuc?K21kgW&uTHD$_kbYFEUm)W>)LN|!k^eO#6a!$QpNc;K*aKW& zid*Y;W|0T|8`3|W#6+NJZsZCIP-4fHAwB|1Wroio%xqUMH66yp07_Dk zr^(ra)h86MW|!Gf<~Sl?Q;sQxp-$0-dtLk+s`vTxK7esE*itrx_-xxe6QHNz#d1 zZiP4KK)U>@^x%Z#mjUnxv<%4|_2}?V<0`QlZd}Vx%dQ;txLUZtTZkiEpzW{?Igdfo z23AoWyn<`&5NE_b&wxc?iYxvlHa4 zY5~|Mx0h@kL_mvh=tjJ>`cpvwSSuhouci+ss_xa0ex{9+Wa&2#>9O*k1h>_*hKoPo z^6QF~JK+33Cq&)%g)}Dvs-I*!RjW%`j$Q3@R>4!_`P+D1yC&MtGZ=N_-OR9RB66hu zFzVum{M-z;7RRdDIv=cdvk~yd7gFp6WtLRBaPJ3FZ`!CLkvvnm*msjuWPwD5`8_wK zhMB+u5!7M234G>(O7v*%Bxg^wxC4`T%bpg~DuR3+^y)!Tp3<2|a1-L%hO2!GYzg2i z(ta8UenHapM+7uuh2XD3yYK(D9FdUhcInr7!TO6$7#eG}P2>&JGgK;-{1+$jmLn~q zbsxyvUv)fEDZUFNWgj7c1bI4y=FXhB5w#>yxg+?^B@Gesbp>J9&)NyszHkm~G_d#J zO0|(?tWcQ|%st_!j1exkxbKDy>6Y`{i2f?mR(*u$Mhump&i5GCJtggKBCGgOxin){sK{wj?!N0of>TjWiSOc9Zx zY({>2%84O5aBYHi#8%5c;4NJ~4waE@CoPgkZfZo^J5u64D{c;l@gt5B1ksyP`0kEJ zb_svntTzEF00(=XRT#D>xyn7-Rg^z+squEee|fl;a{W-hgqVGyLUv0By>n63d;Glr zCNSPBH2gF`e)xz?yZNaZ@)ex?LdUe{KI^w5g8GRlKSG#?j`;1!TosPk)g?lEstA*M zOQhcri7JoJQ!vs;f|yZGOAXqPH?~D> z<(TJ&oLVoQB8B^GP`n73YF^{Yb}%3s0SS~uu`QwCRo#T3P+GYT>>KvsF#7m?pKTLF z5PbXXBS!$hT&b5vxsW9gG~C%dacb^mRXjtu6b>;i~A0{IaIFet8Gs` z+!$|eJfj?{jF#p?A|?RQ1s^?jquGUQ6f|i<28K)F{|G|GBSxMN1||_ji9#NWqfj=C zkPI~53-KhzKZeDmMGrJ=#{!}m6f8p($&-Q$_8awMXUe+Gh29vHY*UR2s2s9v6N>WB z6vNmgj|t5t)|oq2McF_XeFZHd)hyc*4V8eJ;h~FQoVkurHpTopmQgarJ{f+#WMLyEtoK~wV z=_NQ!w+tS=HPN$Sw3Fw=j*|#Cyy`0MW*N=klBOBO$th5`7(4@OfGZVm#oPfRI<6CMJE_!vb5 z4OJuyPRf{|C|p^1z#EHdoJd2p&qWDZ%$O)Cg1QVT(kQ>o-?|{@uo-PTLHw&YSw5B3trj>Mo?VS2@k>k8iylx<+7wT#*wK&KR#$5XEHd2x=B8*yhd-nqn7wFuXS4i!D|*pk29yXN4>g<>h@80uM$Ro zll%+HvizB7@Nhee{5`h>ilp@~c`S6`vmcorrE5F2{MN^?(W5~Yo&iE)>-J?1@sM|T zu@vzglKaj%v6-irW(8Z>ELDN<%v&XLMd#_C3QV+UzP%Pv1fOL#F_S@6lw_brK)Pi zP;z@CmOR55?8_<*rwSB02JV@TWr^_@(l@jg>0&Za;gw^8v@vo|;U(i<(bv9x<9PLg zmHdU{Af+bV)bk#?Dt+w4>nO}6u8nEfK%ou@^{VfJQyj3U$Y#CPk>I>puGUs=5|KoW#K_U*otvc4Wy3Nn!FU=mpZK4BX1+VCo zF5Hmkl(wt)Jq5ds9O2A)(8FQqhRC1!z}p%-+2OaZ`?Q4Nei+anx?{;$5K3 zgLX*6!An45@f`@ouH1YotRBD!^$%i*D8!n|O==a82^oyQ1z zi}7l48vfcRo|sV3fW08}$oTwL^HM1HTPUR7bxDR4E%?&DkK3k5Q=uCF5L9wN8R{dX zey4xYXjQth7bjmUA^uw@o5RU^a;L}m!{T(1@vkS(sp?vzTAZSHLgGW4xy2sutF(YAJdt+gN*a3(8zT!r*~+&+7Fxbvz`s?JC+7Ipwgsh` z{}+f;XwV+R{kID-Xzw6hgz9k=y94wMehs)|86kr!X!!w%8wZ%prfK1(!T;@97V)0l+R zS(7AB_%go^?2A&?PNW;Gr5M4#YHkk$c>jvNHZGy{eF6rymMNoK_lc5CTy6!7>dRj6 z?qD}Ism^w#-etYu_-m69`!Sb{UK)rQGS|PVlJ#!YuI{pL8P5McC%7?EulEc2Y7glT z0cpj7ektvEzi9hV^!w70M&(}#c?-+W5RIZ3#5uhu#R(#my+kE#Vh(QS0!;6UJ9cG_ zBU~KzP7d>=8}x0;dy3XQ)ZQtU$Sc=1&KId(7?NX7)_d;+BFK7TLZ*5PWte0p&jReN z$L#;M5ZeoQYskxwJ-he|N7L9{XktQK*kQ2_|;iF`(!dtOd&uT_M^DLI?ssELVBg{ufsYh3M~MoCwU+S%0$ zYj_EBXR60;c~jL#u6bM4L;lPOSHYy^sUknr%=?g}pppQ49_i4YPGGW0BVtM{LEd~2 zf$dJpXrofdup(>|1Bz2kjA5Z`yOa(iS_%+2{u@_b)Tl%w!)Z`-_r^bvT4!nX-*bv3 zQp|5ex@k|eB-dhN7|E03S;BtFV`U$;D;R%E$uS=gRKz_0Sp?5^BiV{kFOOku@MFjS+a*&w-i*K$_|r?(({jRieOfNXx{3yJ@Y z9EaPy0kIenjL94C0D=`Yb_r}ra%6h@S(^Oa3j&s8^JhhhC|hd8oP?SCJ`f88;qG$I zp#KKZS~Z_Ps53%bAn=uw8okAeRf)*7O{!XZR`yAXcy)Vwmc&U)v^IEq*2PImwzgLL zUsVTkXDskJBbQbg%xrGWKU|GGMAdrMi%g=fNv5R-v+|RSMCrnFZWIVKMNl_COsRSn z(-_8RJDU;k|4ei46ohLeI4-n@#EVDe*HebzGm&LKB4?OU4UHL zcFPheTX83pq`dgT$9AtuQV2V;G|%?1;OI>uUniK+R)qgNncwgG;o;~K?&sdH7fyo)B^aRmTL-5%BAb#l>r8U`t)l}rK;p_OzZ zYrpKwlfoeFOjrx8EkRf(@l+Fvpb3`W7%T5cKU^)9rImFp9cRqR8!x{U`qRj`C+|wu z0jCi#;R#f_=8pqi34_u~p18Ix_c5*Jt-8NVYHhH9U_ajtv(#-D)|;xz!MvBFA1C;} z2Bn(H;<}ohSBg+rAy>&D=|Z**HUU*I7>=fn1w%{%qJ#nt#~H{k<#GZ7>9czj5CoM5 zK@w)138y1i`P-1?ArpofRrSyzG~Hd%6N2R^uK^zW zkgmjBCZbSNnpqV_C&G4L+mX*yrWKE_@w8KHo7!D`K#muxG|?qBp(Y)%gBM(Uf_XIl zh*3>lFkV;iml@IGD77Y0rBQR0{~sshrqQ7~DSH3LBjr`{pJQ0`ftiO+t7HnnTTb9E zqYJyp?I<}3mAhJJ{u)Qt9x}`Q?+pY9W6ihGHiASxWfQJx#49GgYheI0)R_3GG>Q*S zIfyz1L%tP@_$_5xD?DtrF#^|t}a#CxYY2mduhjlF6k`VS`64DwgPc|nv_uksMs#~ zs??Q8bW+n7db~f}!x1tz$ZpUS#ySUCnx4Sd z=(m%e!w?U<_f0%=IZ53keJ9?Bp6`LnCm_u-Hbqu_B@t2)QQ^5wQ#L8atddYoOS7n- zC$#SUbVVP$8)VqWCCn80$u|xUM9V1-*ft(HFBvHnS#tee{$CcOjsN|_=VtYa56>9=R03?NJDA;1i_|?T> zKZ_;v*NN0*z~weA$spg9z{YQcQUzg#k`5NF$_ofm%90!#G{xsYypE+zm2#9n+r(K2 zRG*xzvpkrBG(6O*?K5!^-|iyosx<0+R-g-ZzJPOGBkQQ8Y5BnB9VVU1%`wQHDC z3Iv@pgw(HOpCbXp%wu!u88fSuohz|FW{NF=DVbax-!^ zak6r7VQ{gxw{d1LH8Xa#urPCCP&ab2`WNHopKBS#s$24?LRfqYc5BS^%AaWHXvKmu zu&^M(ML}t-)){DBlzYRKwmfU}^6rkljCbJP5Zk~ET}Y@5QJZgy!}cv=jJtAcrfxl4 z4P_G$nj^4)O1Po`X zO_||V@H8&PvO{j4lR*KNQ$MxuiSr<>BbY(4qAD(6dWoxlAO+bxiTvo4Cd}vPo{m3K zxewNr1J9UuvVD*{P-F$%yOJ7^;mkXVK$OV#{*)ei$zZX4feUmUajRxj7Hj#^Ac4WR zQa7eoKYitRxl-iTeg#g7p)94VTq9Z?#9a|I7;SZlAiRZ)ilq;Z!?W%YIIhs+#i7qshgO5B4beq$FYB+2Aq1>$MvIYrK!ux^T3!L2Q@ zR;k=h64?3jo8`Y!vM4HcZ}ObOJG%nmo*9RBOj6#{4v11bf=~ovsH#=g$O;??6J2JK zE&uq@$|;@AsV6J|P! zU48+qbF4xheXK&?GRR9gg|^eQQ|*B8c1_~T?-Z9@8AUFt=e{t?xkZdxOr(f`#rgPc zDvQP9`6SgI$Z6D_C~_b zSVu9N-5cE4E89VE{ziz(9408f7Fp#a5{m|1=cQw)5FJjAS&~i9ZVDGZYz&~g%T~3r zYdp>%-Mu@a=enoGW@A>Yr{YWtx97UEMsI1NOSMw9t@OssQ&#Iz^{2eQ<+>B?7e63w z8KGP+k)Ao|0XXZW>*zLk{a3h`f~fFZ(odWxeg6{X%UbOqw;EJKlb+5)uM`!d(}j7u zQylGkMYx5-C2Q);Ddw)Z7z5U=cq*CNhU(Q}Y&RaiYS3BkC4IZz?kp^ydelMz8;Pfi zs7UJZ1f2)j&sh}2YOgc0Zhr~3pRz&aoZ&?g`a*BBwfk@-*eH;>a3WtqOS;idv0iXC zVnckh){obnXn47(Hs~yA=*y6YPqIT~aN}tvX?%7IzJj_ozcGm9s`M6DS9cLUkP5Zm zC+rPE%yEr>(vC3TxJ5&z!@z-R?-_iee$9bFoGHl8N?-?&hR7$7+WpvN_1#xu>}DVgf2e95T^1UsZyN*#cz-ix2mE0|l>t$=m^EC8J-Z{}PCc<*&=T{az_9 zee|thhdjV6$r5Uvh_a|KUy=}KG6qTZNmeiv8n-=;E{2B_{OG@|A1-{gc{o7>0SROL ze_6Nu=OOqvpjoxXPgPwF^iTSSHkJ`+BtuCk(xEhRM!^uIKxk26W=}b8BsfV@E0xea zkU#+3b~;h)a?{ePM3lYW`dgX0t#&506b=e5>d($99N%*%I^Waz=D$j*p9{rb+P%)l zPS}PC#-_^|UNd~pm-aUw+1yhvtq9cU_Hkb~(Ot0Vh)DxwL zr%_$r+C3h+(|km?q&f4B>W0|-g$G%J(DJZVLl#Fz&LFuXn1`E~M@NoU&tz8jX3!7l z_y*`@11n%XF{MYH7KcZ;_xEz`=Q`XySN)CLJqP{nd>-;6&o15uBZw}%wf!rEYzK4w zL37zS%r98-VI>RV+JQXF`1q-T_l5EGr>3lFVdN44-PkNScvh*k@AC4aD`u~? z$!t5nybeglEXjYOtn?c8KM98FqOKFhT*h3UT`eJT<4C2G^xrL(dk`bTkN-JK!_FNA zV<}f9#>ZoZXe1#C!Ontik0hd4KB5p5otb2YhmRcGz$YxtUyv6r~M(?!CGrU(%(w@H}z>k8f#1f66$=xshM zH56+xtOy7JVc!ebZsP0}bskwjCgJwRb(a|Bp972$9SrvG@o-Y%Rk#yds#l=frVnjmkZ2GBP)*v^mY$p3idiyW>>c7)nkj4&Qy^0S`6!p{1*z z)qf1A3sqQ^n>Pp_CneBXcpfX~oBGdaagx~3z{s8)%0?Yt}+>$`m+|5O;D zV7m>59uwlaP5d&~oS*GQ1IE1Ho5`F!*=XcTscX`DENL*GT*Xb@YOm73Sn09xE^K<( z16@4_n0Mv=di#Q)?4N$G1Fz^sfSIFnPd%1GFJ8(K zIUE*3bN7l6YsV&L?zme!flkn7Xw}@)BnZXwTz=oG)~@Snbo{K&piE!U#^J`mY*d9H zYmp{+yS!zy>4_{l0n4nc6eGl5q*owkOWfOZp1(eO6C+$mDoGN)Ze&`)e=w~mik3w@Y;Kje@!;&UrF{dV430d?+&rV}Z z*qpTH-_eg3WyL7mah;l)5;aC^rvxZt!pvzJDAKfSCkvM0kJ=irqbh*8XP7^desC{P zB}#EDqu-*Z>k&vtKbXdvE4QmSvZFrDRFf%IktwbgE1jiJvXAj)cv{9IPF%rXFum%` zPG+fk)u-(na0Y9CDwTs)V$fG5yp8lqR~CUe(T_SJXS~Y#D4UGebf_?WgBNism})m( zn$q1PkahhlXXz`Z*VO`(P)~XHtvMB$pk~e8Ar7sZ)nH_^Y&mOKvwp! zENPwfgD+q<8`I1jP#!b}|FU&$>uBzML=V(Vt?8^fk%BHST0(MLRU1*bX?=26`$dA* z=AEWGSgGK(mD(^2p-jE&oNn*TP24;bFtijR8np&L{irT-?+rd~o4v)s)AJv$oVC|a z!+axzexnHZ#2(u2Jq*5X6?ry^g{i~heoC;#e&fGv&5FKD=PYXyNuBNhm2**FU}l@y z(0P2~`1Q`y{UPEBdst;_pPa(M1#^ zdns`CY2fl@-|?lO-%x4$TzO?Gb7|T+Ys>Wkp6j~3L02j^ZsktGU@M>OlsPeX{?u8i z%aJQ)mOOD|SMJ1*IIYWhusq%Spgw0K35-G7WzSONzKiZc6`@FkSB4>9g-Oo}%fas4 zCFh}5_I~yYz5<=b4m$|ng$F@9tGQ4DU4!ZUSR|qm#%+lxCabCHNFfpX9ERIqoQ0zUK(8J2Cbc5|icdct4r*tWww&$F;fgbI|+ zoF4X+g4!vyqYQD!%m;31h?;_=nQ1FpdsiN9*WPP)fzUr{^1b}g4eGHw&hSSHA`I2G zf9h^{7s@!j#Vsa2gp6NGo2Y(S8^^gFA2p&vAn1&ZAh1`IVVl31l%wuOvy z?8Ud13xY~rrnn?bq1#SVpJd*ub5TX^qo})OkF-!LYqRw&*nTfQJWRn$mliG^QS_tL zs73!y<-N%mt*H!_(7(aPO#k~+q3jvrYh9ZNWxu}%oiq!5cN zv9wNxH;Dd@G3Jh+lz=EOcHL>Y&!&hJooT}hO@cl>a!Od(tm-ZcPV-`Xv}6$m(t31{ zG$v6-?vtlM!7kLg7bcx=Ompfc!)lXdN$qKyYRCdwdac0oq{0KGc%O-0t z{=c4WT)ydqF8>(Y8H9|TU7UwCKS#ve5)QUd5Bp{Oet zFt8&7U?YWr*{l|eBz5((T2`3NPvg?5aB_Wa1zu_x_$3RF$cXsgG5<20w=V=6Y0IJ# z9M_!iobc>$Is1ORIzs)3@iJ;6A{cPNLfN0P99lxE37?9>G9Pl_3&J&GJurvGagc#? zCYlVbLmD6sv^i}7JZwtOPcr6s7hhT0tG+kq%#?eFp5VKxMM=f3;fWk{<*eWjKqies zh%g$NbBTB<&pbc|SF^S*H#Z4U=t;2@V&i5MNBW#Gp4yzV1ElAhoX%5T)j8ng&>gR$ zitTwSOfo{M%{@EfCLCp4X{Yi1Ra56%Osude`r%F3DtSu8R6CqDo$K{3PIlWG(X8(0dDST;G`77EQ8C7_dn&BG|!B9v@7DPa02-$Z?m;XW{SnB6_9 z)ASfzBU96gDT8fu$WFL@p0P6~x`l@>e(THZ*dg-nnN#2HC27?$d&^-)JgZ?kN_!;C z1>1$pala{uLvmvepG#>B+iu3!lZKd)Vue`eu~R``hal6cn^qai4eM1g(dPC@l&k$! zW_tW(J#&b+ToNS>Xfrm!DkW*0KK31dHSouEImNCcWQMY$UC-)P4mr>mEo8oHOJO z#UU8xN7&e0EtFd!QA?}f1Kgn{hWcS?Omt};z>fmM~YGG*4Y` zsHRiM$B2(3Cv<9+=uV9CYH;moZFKZtt!u1fQMDY29`lt-=zIK>qgP(Se|{f_o{7+R zi$-}4@Sq6#!xy14u>2~?cS_Bf8y3@x1`Y#yr6NO}5f+0E$*n4jD4^*+n^lZ7p_ITVM;87k7{LZUzs|~MH*(g&Mh{Sr zK%O<5H|i(!pQyRExXkS~V18Lt8Zo(7p{mPkO<7gKWGE_?t z@rHshXtdSyQui<_6fB%9R9Q726pO*Im|N@4+Pp0%r_;f(Gmd+`h1(q1#DwurVS1DA zZ9C8IJDv8wKOWW;fW#G}3c+tk9YAi#JzS*_QgN9gXcCynLn{+_YWB539J^Bc-rMLy ztI)FJDiQb721B7`i72cVsQH!SDYB+Bb9zr{JA`SWWYByT>MgPo>QeMfOhnqi=qxq{ zrnEy&pkrsL(X9(qLi8GnROeA^tTbf?{-k-ca0umD39BsE^X=4qkO3;fRxw)>dp~NT zy+ux|Y?9!1npU3DV0jylVewROx;y@>atyfsalE78~1Wiu_Xe>e^_FDk(mr$R}m07zI*=(#@ktSA`i$0~%g@c#wV+<8h&DnoK4jEa=i!jLlJQWcK za22t_8A}dDg=l$K86j}6x)e%?;9v(loJ+GS-n@;r9jnn=Y7WZ5%Q$JK#QzS^p;l+z z94@8iU#N@d#DPPDqN$}96+RXOCLiQ0G=7D2h3XC^WD)LEqW+i=!jbNNuNTJEPn}r|)b~9^Wv~a174lU^a9d3u2^~shigRwLvbx3s-Q7l^8Se z5v)KZ;%sRkbx&38uVX9PT`s~pFLQbl`UuuLtK_newk~wKs~6-RVM8v+Ox207U_5zY z;(0yMm1&d?HB-tQs34S1h%{zHGM;-+VvNj-5S6u89}Mq5O(G5mON>cm4FE3rX%n{O zh+%&#+mIhz;+jLokm4B-a`Q6;hcur4Mmc6Fsr?{$TpvqAfTq%*kf)G0czmxrCH#IL z8Rwzj`1WLkwuESmDzG=ku!j3Qc$~da(ds(`hggcMX^wT>^SThX6XX;TRMC_I0kmyY zQCj~m*M94&qp>fGBMQn;|yUI+)1{0U(C|6pKm0C1y-yWRouozI5d=X z2O!e@y6|t@CSV;CmRM0Cf;3wq9Mvo+^6J17$GzQuC*w^&yFpS8Mw{onpq;ash*qk^aQeJ#+yc*zVr zK(}Yi3UL5Jo@m(xOq2jWC-egh2}Iw*T_GhL05?4;e7h!Kq}4;tz;B73KwaJNxYTQ$ ztiX@ko1+IsbVwAk&b{UHmi76@yv6c<(%btNVwYH*#d1VP%VqZpZo9t|BBb$ZgAhxRy2Z2gkf)_!a zzu0&1Dy3C$3f0OAOLB7nLLy6WOL^X@N2L7ecu$F}3<%7X7nbLhCn^~Sf-v~PlMnte zA4LQ!!xX=SN}0Q@|<_B@h{SQQMZO}8xdy^>s|gsL6tNym?=saZSc>_*iP z`Ia=Rr7wRi4?=9M_(52vYac{!OAuLewUz`*7bRArMAUMWQlLc{E8dyV)mS?3Q{_e3 z@s|aO`D~$|(8a>|=)=jn>;;7E`9>COcxDC@ z1h)nn!qMaTG47%H*>2OrXP7MaVdpr7VJM}e$UxTzZIjT=V_Lq)Q+}FV526T>Qmh+D zuI^rUYb`<-)zri_+|RGO2}))4Q*YXMuB%iR$}2{9(}mW^F?#Fczek|84aX9+8dAMtKh6VuV)p_0zf{nm=iSm4C1(pbh6*07EX>aXWX=DDmkR9J6m zJATOEJ5OM4O2Dn=adc$ErVFm|VTxj)QyuX!L@s@`ItL=;Q2kjMMboS4x|u7=VTI_P z8n=%)ih%F|$MynLp4%pqpW5W_?$it&2yc=kqe=5NHK6J3WhkLBUGgIRlqsNPEIwtxFnh4RAW z(!kOi&`9V4Tcw@8WoPUpM|tQo;ctUyfPREUyb)W5Ath>d1-6AMtWyO#_!6{%>mH3O zTxJCYRX-U-_Ce_fFD<#2AS}J2^Z}=V3}$*!lHt!B#Rc8mTGHKp)c0`%~$rcA!ol=}b07Ncxt_l>yxr&6z0-*84%!}`LXXO+`E z1y>GI4xC>nD+fcjM?2!5pz)<{zCBU**h)KmXgHRq(f*8Rj zyjAj9c6?;G)f(C1g0@<4NkUE>Tf516c>ld~oWyWl5O54`{S)eq%UQNQ;L4sl<@ed)_j*?{EN?@#Y04{8q7RSqb(r8 z6wbnga+r~37DIBUC5!3|vgJhnI0h=r$UizT2RA4MS6)kAO8kr0(ZT*z_J$B79Gs`l z0*~vM4kaDc62ams&!V=^A9;qs{G=2&Y%L&*3O#auCZs1R zUo7JC7HkNb3?c5s?`nNd$baFu8!4LduQI!4(^i4F>C$$YM%;AYHI;vfPy|RdNefME z>alrI?H@31@h;v6LnhoT4a`hc2aqwGuRND5rZbEp1|MLOla6^pm#QCeLD5@*2YeS9 zhWZ80_WUufxqGFCl?!A=PjC`_(-!Hf!+3(?jRhgy|~LDF8))nV#u%{|3znj~>V zk-KS4k&Q%C>0D-P*R`}m;hdMrn;Q3PPm0%vo^0)HDj5_ zzAgW)%0_$)4=?CDc6|cth-9{rT+8F&xM^2bB4EBC#@1IO(i+(x4^MYyCPa``SZGFv zWrIlms8fd0SvJ{!3b000LFd6rMKIGcL|fo3)S|(PSh0g+b0zcTzs2S=6)67oSO@#6qVEDK)GjT#3 z@8aAt?m+R{9L;F>L2M6p`TKYfL+l9p%?e7vE9_Z;Qe8$F_4g5{!0|=~GU+lpAg980 z6*p}Ulldopx!XfEt>i)r(QbD%Sr)jmsvP%jp;lK_|H{^Pe%50XcVe?-=CE#8S2}B@ z6rZ`Hd`gS{qpaa4N=42-8>9;}a+4*Y=F`}YQOSF)e5KA)*UbI?<@L69G1Q@d0uJ~| zK0U-ka|M4j_A%SK*|%3b$j?MGwKKOWcIk~0&5?pPcg!udrin>@GPLB}GOpfpt2rKK z$kVHruJF43`)G!8wJ18v=6}JIIDJl z+4sSO?h56f=5CkZlr;sS`*VO?1HDwNHb0@J%+eht*%4I|KgkiMKlC(7Co1vIlhG?! z6_xTC(}saUgFz@5br9gV)@bWWJuATc-p7`>8aS0re?4Y_sGO6 zPZ(sqR>5!*u2j}j^E{V%t!-YkLev9b|3e8leFMr&lH}k>ska(RmJfmV7Sre<|08$& zh_TYEmmJiijq-L&x}_ZA$)XA`b50Yo?4nWBXBDnUh>`NXNDMM}NrRsE-61Yte6Ky?JA z7E8{cGiMRWFM`m@M~yJ0k;L#Zj73{g^}MlG7Am7k*7Ng>2Qk)XV$xHhF_w{qk{4Al z>*>SaCP3i-tmNve(gIPwjY@WKKtO{3qc;1`p;X5i?H{Vm9ALwaiozZQ1>6qi!XhNz zMFi&G23^Ml9ajlW%Dl$61~)lP%hE_%5Z0W|TZe@CvvRt)bY{iCJ$IqI_v6n415nI9fD~b`E5HVYDXMArhrSA9hA7MM%S2lM ztQ4t3ynw;}l4ybpIlAl}Z?z$LxZ9^UQX_9yjUj!w{N%$ib8g2#B{+o6;gvCnJ*fj5 zFiAMs;i_>C8)3MX; z#umD*C^L_oM=)+J*Ky4TQ*rHOhwVpv<@1U}c}X4yJ^sx-sTI~L?6Y5ByxI6DNF*S( z*dtHgfF}#MO4`h?7rn2~%xhSJWgxEb1*n{SI_912FmQ=I+*6U7Py1EH= zc|YQCT%8UZgkl!>QHDRz6ARoMfJa7ytAFDo`m;p;LMfsg_hLKJz=8e}p-0n_O_K2h zq%LUrm#~I5RR8elkt)$kb5IAR@=@VCTX^bXg{9#aW6U<&!e}K&DJq^_E8m@WDSj7E zzsR_*Mo}IOpCqHmZpciukee3qiatYDS3fK6A$GWP+~F8zQ#L8)FP&f zSvfZwDQv4c!rGU6;FhXo_2)$-W?j39^E8+q)?n(E+ML`-rQmC9CpL+qY-l*>4DqxT z?(3PVc7;BxdHY56g@0Wu47Ryxi0mCnFv#J;h;IF{i2ecJoWQo=u;w1D{3tIxo>EhZMY({COInkhZ{!L6$BYXNb=2$jm1 zlQcED;b>)j@9wtD4%>y%vK;gat-9lQ$Pb^b&r9!lwXi>U1f)(qW+$TY*EHLMuJ(!6 zYS#4kO>ZKDM`HR#`Rhmm zHdw7IkyVAS6ofh7b}Tm`5dkm+$W9BSlL7e)^91}MXI6fNP64YO(T9u{g#0Zr8~FW3_^@TLbT1h^^wVPs8!MAq6FZJ{8$eQLjMR{k8aK%RxneKN%n7YGI(*_w! zPB|jECQYy-+x#n4#ZzyIv)3`-1hGc^4F534B!=P)pIriJA?b>eVPzF;O=%*I;eh-wBcEeSY9vvTCNu$?PiHEpE*JE)V4;) zE6Zyg<`v8Gj}7}80egc+*j?!R_5oGk)aZ9bz+t1HeeR9s5nP^iFy6OjuKsTEw{-?X z1*{qJhL&1wi(yO6>Ul@FtXs)1;1#wb?%V&Le)|s#ot$BCKGXO2Y5Z>+o#=m~-~MY{ z{x|E8ZTyrpC=*(+!uops(z5keAEv|kz;1_foKXJmOhGZMyA|$0k_&NSR7C9Y0OW1{ zAdgTHNh4HhmRFA#{n*O$2!)>v9Oxs+BPbl!x^&0rsZFLRxeT5N8=f4tw(ou5s&vS2 zPW&y~!N^^0(uf&d913gQzUI1=d=1uL$==agRVaH6-`+tPT8$G_CpN2f;Zs@t1!9Z6 zm@~)rcp46Rzg`?V1eaqyhyrLwAq?6booYJYtRIbDR=-lt4g-m~0hAim*I(SMZ z*hnO}|KtW036@XpY0@_-GeXSMme{@E$62&hZVdqKAS^ig!ye;(wVU<}j$(W6POx` zMpo>B*z1=C;af!(9VrHxuOZqn4axd^Lb!MmO8x}xsZ~5O@~hvNDc!z=yX-6&PK_A@i7e8{C+Ev#S6pRehVGxvsPY=epSf_qz z9+*hT@uVba<-^_GK=UYj`avS&cwiCrbvA)qIIq zP)DP?D8h}&jvJnS*+1KUxUqNI&FAVhUtP}Yl+Pp>I8AhtpwKu~&5Bj3tW5c{W!eRv zeX5<={wO*Hzt1TUMnrNW@Bz8-7CHj;QA3I+LtC?@jf?Ig+$W|7{JA5pk;T@ZJ;gfa zA?)Wbe1j!?^ANtc_K5ju;i-afLbpeqk3E%@dc{`%=W|?r$ThazKa+L&6w(=1F1FO` zl;sZfKc979TE%-OKTTXA)_TtZN=%fZzgxkdH>Z2K)i+g0{WtKbi>sKvjPb@aI>(m;OAj^fBEx1 zq5$-)L`58mi*T>$<^WFvzDaA??8oMhy#>2)&*y(K^_}YV`<^O__zZtEU)Bemz*>Pq zD(M%nE5sH(l>!Yh9S^eSJM9&&6$LcqFPu>kIqSsu*a6PPSnw7a72|C?*hA|oWX>Hp zlXd(@o}#MkK5v#gv&9r@)`NIvi+L13zl|^xQ?khY~O? z!mfu8vesPdI90dNlMi=U{*=kG(XR!^uM7i5SJ){8!~nuw)f?~NvfmQNEV0ZE?Pd&i z2K%(FHOcr{0K7^6+>v19J?Q5UMx76kJNPwJ-;wiYkF69lUG4_lZ)NKjc}eGCuB@GD zRXaROuORC+)x=?9sX<=SZMNR2Vx^_q%pa+_&p%Ro=$cd|AV9v1;tTYjYj7!8X8V7! z_6|{^MNyh&*tTt(FYv;)ZQHi(7q)HNwr$&vimb}6&RRX_9MtIE`Pu87jsM?Y$?xT6 z_1mrezZZkd|Eb(o+>%-RrACBQxwN3Et04f&vuN$6%fSv}hli{8>7j`w+3{__Z4nN@ zq{)aMl7@9cLQ3=p!}kgz&Lm0i225DbGoN@lPP_Vecz8QL!S{l9niKR&1&O9cGeox` z&E?Cv}*p|qxAE1co|(3`BE5y7pzP)ZXx z_mXVw9uw${sPj{aLU_V}t?3ep>>iDyGB$fZ6|&DF=k5ZI=Su$#_JYNC7mEwQu~7z5 zupiQTSaaK&9)}TbZwWG{kg+dty>x#55AhA)Wvh4j+2fem4Su0hF{0(IfJ;yjOU;QuosXp$U#>wllRnqQ`u%@bm000 z`;9i@Xp_R?KWh)hl<2rK?LO@|-S%?1^YeX2?uY1x<-xcRgEv{04HXw?H={pGyuU^^kDl}Ar)sAt2$g6nQ7D12V+n@RD57rapn!)pX~T_Gad%m%j?{F` zyeWH7MqVvOhm=%TsD1@I@{86XrLnj1MjGNFGM#PK37>ISoC!%(p=t#hDE1*2-i;y^ zECh&#rxf#y@4|qlSMk1dJDEy(F>@|uJ2uO8gFJ`?jgs z0iNU}%*qVo-FBSj!h0pS6$PgUa_Ixu@k00m=L|h&avF%*sUUPoJN?Z{u&nlLrY;*Wcadx)lhTH zn(X3w$bOaAR44#yv1))@X@GR&LmhCVf@&z%q@8Kp!#;zZM+8-e2AWODipW53AmhHV z)EKpdsXBnVK5q?Db?ywAaFUccN`Q%>@B`v8+~`k!Ld5G}QaW@xl;>a-EuadD8KF2A zBPcV37~oQH(;UH|XV)uVU91C@9C7X}H~^F28rHu^^>egf8CFVi_JUOHn=B)s!mw%$ zQE;R>d8>|pxxilD6wjFK>o~Sta4+1UIAw(b&7QhUg3ZvhS$_1=XCB&f8_-1D=zms} zb|!s491Byhg(w|8g2uW#Fk?9thuSQ7CB=6NmIT+{Ykl##TNTU~)Kecw^fNC}asyOMIbXa1iU0?@&S}irV<<=y!9F1I_4N0MD zp294#+GFxg@H`{N7s02S&(VOd62Kr3#|8c@DE_NZ&_L~$bx2UvU3}x4IxKY0PBFH3 z0zn#@P5h@bc2scPVomsBmRBjeYT6bKgoc$-I)I*t?U%53L1foTpTgWg8 z@%;q>cJD+GK@%yzqg;g;ZAi0~Y)g?jzrjTBUB32SvQMP&nPO_#f-we+u^G|K4BZq? z^mIjd6^%fo6&36`vT%wsy3YHD&fsC7gX1IMA6eU_9BcNnGJ(ng+CWEwCbz~d-u6G# zR{spZcOdfyAMnsjlGhl29;cAl!7piC7g5*_;@)FSQ@^?q`wQdMlYUW)&#Rx|>|9ON zAs->mh}qS#RlzYpAYWtn6Jlr8ru5XC(a$uexJs-=94CdY8!_;#d1bNbRpnHc5<7M~ z=fvg8qML%qoWbCoIq%hp7bj4kQtCoHH%LO-BbMXC14v1@PsPBx3a-!pA|CpWN`TwS zHjwVu%&~#^-(VD*8#%g~I~khM3;sHpN?Sc@{aCQeC2vwy;9G>=fu+Pse5vl^|0l5v+~pCnG@DL|DmrT z=t7(YIalD6l0n3txS7;S8EPIe9XwZIrwFUa&ABP{U`Hl(at8E5=inHQPUm=IY@@Sx z48>kk{)ko6RXvYQrJYQ{l>Ud!!O4t;wbS?1?7Vk2vaIfK3^Ba0P^cngqNv<3CG)_< zejTcJCRb=mxWfpyfhy5u%xN4od|hNFmDwcUEQJioP-ciu`Z9^a>Yszk7^Y(-<*7aR z$mC?I_gDf&YTEP(Z5Uf7)^KU&j4Ca7mbS~73m7Ss(+kc&F+94H+BRd9XE+&IlS(KQ z6k0a5>GYuklcD1}c1mv04yrlDf}?REgLx-bHsO3J7!VXhXy{aYf7Lj)R%`u21%oyxjLGOApyxx(yD!QEHjzk)i zX|zcRD$Q&mf3*h54sw>q4%q>{N|=4HeHnr}_30c&CQF!fwVdLwe3Rdj z>Ywo{kU$EETphCE?n9MIQfkVKGEjvH(QA(CdHg)8zcj&8LyL9swm_vh5uZte@h#*_ z88TU>m^f_-TAP0|L?oEZp3NF86~RhR`$oku6%~%pL05&D4&{2(Cv+w9TtH`+i1xxVF2zVuHdkwR>^O6VvE~ZT4{*snXb=QK1*PGll#agP=v?> z58a8r{< z6m1l5i{)mco3l_Fw@4PqpcDf%%%FwMu%Gl)9F^n$cD+h8B6?~uLwdPOGup`SzI4~; zrf%vGSHAXV1S3G-^j?E)TR--9WjN1&3AAr*?TI_uLgVNcXzpzW%8d4uDLza_$ovuZ zhUY*Oc012nsO~?6Q?f zdh`oCbFTVy4<`z1!+QDfz`E9vhusk9l>*n9c`(H2+Bfj2VxvU8Od!5x z*9QWE16wBXU&66sS*9x2k$z%R1i4^nyyUVAST~~U+yI-t40s>`dI7$Q1gi$t;(&Iz z<|Wsyiva7j5~-lc!|#ujqUQR*b%B{}!70f@3 z$ho3gb8Qse4yTJtRa$bL3f{67hfeXQH{D?FF2mVOH=r41w%Br(?ZYf1KIIF@x**nN zkgw7dP|)O}>tQj-t$$L_mS8w#|DljJ%>sF&el@#*tiE@nlfkrgzq<|2$Tw@$2%Dq# zI32*QWz>io#&;t&iDng>$pg6S<-}Z>r^@=(v-mhH$P1Ye;le(iR7)hgy#lYV;7+Yt zmyHOg#-~UXAe;gblcait2{In3UqvK3>pl$%wL7oWG|ZEZy6vQ1!C#XeLZn6@3^Rua z=ltQ0)$KLkwbVUZ)PsyXtt2p5MuoW?JVXhbGY{Dc( zIb6p7{7;z^;9^hM$0?G`fpKM*mS8I0ju$+{z_IeCP-GD2CGxQ(N583SjwFUK{4kWc z8w&+RK@ENmtQcT5VV!K*R@jTkp}U1J+hd=)diuu=d*nuxTUG|xzQ7|@QjZ8%S4`vs zEJja60#l^q9@Y4HhFHHQ2evJA%SWvvZ7&XrxSt@epEob4t0&4LVb=yVnOk+MTp^!6 zc&-?&Ll4eJ6G9Q@r}8KE-43zC-`T(YEd%?N4u}LKS*I-D7k4@RIf99E%)pL~(yp^M zi;`ySr|yl~9-!8yI8Xf9#F%qw#I)1aazf|C5e`cE?`QUR$qRLs2MtITBT?I^9WuC# zU*paesFnu8=>-eUzZ$&_#d!}&sTDfyHbLuaDY;3O<;l`N1&2? zaRk=~K93($Id``bD!89+O;MIxoQhAxmU6D8bSr8)daBAgD$a!OW)oiL&KZe;h$jIu za`5JWa%hi`Ed-hk0v%EI%JWe`$J*GF@mTirx9y6=UkY{y7rv;#`ee(ds`x$3yi@>x zeuCAV&6_7Ow7I}C^kB^1wcOsP7JSj=ULp>@Xn_=b7abt@e8bed`!D zOth?#+5m|^X1|mhZu@fFptJzUU!X7g2z2JI9s)Tp^5y@?BWI}au^}6%?)meG$el#N*v?Ad&{*8b*!q9vVp$3szo0$@o{eP{ zON)wS&m}5eGycF`SXy2+1R&u)i5>Pc1=VJ3@%^V7FNy$oA3uE3>0(sS9F|&BvVloX z(|Y$GH*etD=%qjPsn~r8$FMXQrH8di15APtzy#ADXo`#oKq^BQ)Y729MCGLpKn?8u z^Z*H-c?LV)XuKX0cG)zqzGG9DJ9(mIf zb4$NT^>a$n_8>-7%jwe5Dd{Bc_VyFG;C}k%HW?Fb^l}*Ks;4gDLrPUfyLgxmB!GGzgI|*-!P9- zL@CZpJ{1k|C#mReAQk?gI3#3ZTB~oG6LTkRNzXV!cm$hn^{8HP86iD2C)4Q!Pa3NrXGBM#w{erc+2JWlJd`jbYP*niJX=jcGym)f*O3Ju?#@H=#?V_zLxhza;F} zS^|4=Hf`4-8kCF2aJTtC$87GCk}riaIhl^P`+$p+;)Ro~0A{6edfXbw=GZ#sX=}qg zpO(}2K&;1@X-3##JIa}*z_s#^lgn@*RgH$COl^z?9@XQ%{5{zYsn^4QFkyceWjVj) z021fsDEV=3akzhit~RjNx#|r_uTtj!wVk?oBV}CAOf&B8M-quKl&yDa#+W!fXJ$Em zkw&DDkx#_ry4x_GOupHaslgfgTR>-DaAT5PuLtwc)r^`96*bFU5U=VzO7!Hfvg}Ev z{0aRF8fFm*6m^9L@f4ultv23~Se>W}pH~M#QL*<>m-y4`6Gv zq#v?QZ?EDtJ(vSYpGHHiUsAu*Y7b4PE^aWML8s{!OQ+=)6{p1xP?Vb*zY*fnQVPiW#CaN%;F~=-P#crbvbm!Aa;GiltNW!X~#ok+n*y68i*&{7>2HkX2LR zw+2A(T1l`mA*LSCu8}Y-e1gW9YNJIAd?}I@I}&{vcoJS#&t!HUlk+id1_ee)pRes5 zg)!;W4e>_?^Ib|0w{!rVLBc46bV-n7Ob_3bIjv()&IrKlB>kwnS*^Uo2dd-07Fhz+ zJs^gE27_c3SK`zH{}?^OX6o}2TKFV(I6vNlbm95Oh_>0<-DrMxM{g7CJZK^7WhiBH zVLL+SZPn_UZqk=hz$q72;AN=A_-Ir%@ya!QgRV$D6Tbt{hKjb|>>IsU7}j zgqQx!(cUcG5eU*A0Km31`r76r$rkcqc;m&Q&L6{_%Q7MD^F?;X5Cyhsyz3bN9z~Q5 zMU<&8KZr8JGTlR(!6ectHCPi_hob@+7<{CmER!r;niL6`JP)&o?Z2mi+pptMdRVOnR;uh`g*U~&o@j3|SHuJ(S?!HrH(T*nn z#aHy{2wwWeq$p9DXl)2Rko8}r#!OJveL>8nCaeYt12(-iPI^wIimQ1F*3D`=4H*)W zZsIW;5Jn73#WyX_AwkPC6_Tvncq2l4%W${MRW?UoIf;Z3*afC0xg);*IeZxO^e?4l zN+UJ!j+F8NUAd*Ae#EM{<&yA1wb_@xrgJ=@?VQ?)y@m4`R?%}$D2qj!ajXmxpW=0A zTXfedTQ(NXMhD%A=%k5=r5?RiI*U3$o0+gz&Y&S)^(1V(tR9Jd=|T{BR<_xy`n>KQ z|M&a1QT3VVot#s)9fsaY96e{YblUL3 zSsvav`jdp%G;yXOD73c1zKCgkgN~P0!BKwdYC)g*g7nKP8CU1kb-3co0oP) z?_SKe8~sA~pmAhaKMdnDq}V);eY|owYOD6Jb3govn|ANXbOUd+0=D)j+8N46i4&vj z0BaYvXDk8jx;{1}Ka>^rNe&6{6E@%9v`|JXlo+iH9G!jWa=Zh~JIW~Z4gLRSU;pte`vX084gY3e@W0a{ z_WySFC2pjmZ{=((r*HoMG{EGiY!>(tzL)E=7C9Ozu8JnY^#oTNmLO;hHP`RNxwlMV^)$5^0%2$s%X32RIE7oWVYs0x$IDM!zuc#}< zc+StC>@V0C5*rho(i|#!%@BiQZ=8sngcJ zUhndMKEg#wWRl^7pzUz-H&dN>QyUaP&fsmX-8TfxjF!I}iT@EAALFOPaTvd*N;&`lhW~bGNb8&1{AaeN0qK>r)Wmm^;eC(T9|TCA20^yOM+}lX60NKu^!P>)zpk=txy!LVPQ}B*RW`*+_`3n zj_#@*)eM&m#ol)X~ajV`wCf z)+JeVq!x-nPoiX|SAAj$r+a&%YZR`i);5vT0&w5wfoMuhP-rVZ7eUsUGVF{oEchNZC!9(|HQJc_dd zP0Btpk%>6o%7a1~YZ%f*;Tpx%(Y)4Pv5gL8Vn*SO6?qQvjtRT4Te6f{eBIK#*1@48 zZs+n?m5l~Ld!^%o0A0ecM|`~!iLKqO$XoWwE*m>-av=SYw893>(3?y*e>eI#*RB`)c6i=f=3vk_o zL(8osgpA#Z%BTj>%)o?Pfm(q>^VB#L?2iy?BA^!+U6 z!iJIu>+jCd6T@i71y&a7jLY#W^&VH{@5g$Miju_0?CO4M1`e@T6g)6z2ZiD#WD89D zg(LlkP(ucN+j1=NMpO)qmy*JUOH*@3P+aXA1z9|KO1ePrta!|wrJUKPmDe#hF~bIV z7MPOF96j^TqYjQW_}d9Kv1M za_sG0zeY}}E_OuQSdzr!Ukl5KY(k=0e%cB~=kvJt*dLl{XP^x{XaQt+R*+ z5hP4dU~wFzA&-RCU#j)0>h2D99#Xyv$*HlMsKNllEU83E$Mr1k)X!l*Go3B0tLtdt z6#a&yJ0VvwocY9UUW$c);Wq1H;1#QHcrB!jeh|~_-EoyCb$trNe@nr$EQl7epoRcW z42GNYQ?Sy~#?o=yF?R!idX2j=bb2JIm#|F(aEXR@uflyX9CXZR5-ymeVXRg9!;E{N5`0B^*@SaR@$A$8 zwAFpAF2Y{MR;p|k{*(}!CXS}1ukm0_=Z7DzlDtOoSnLl|(wQlhJd+X|wu1_aU($v3 zl1#F(+E=`p4B$b9E}`H4QT0YEPMhgi58Cp}jq za8+&*+ILeHWjHn@vnHJeJ@(@aU`UA=*ztD6@#CAQ6LS+^{YYWR&!?x7ZM&uKVUQU0!2s|d7eyb*xD2_1d?e(_Xa!YcZ4if( zEbECwx5EJTg@MTXwW|i`w-=EUZQWhP>&fcU6i;JCIvL7vBuEJ(UM3^BRz!GBCbvtMLHo@FZEWx^1J>nqSf`53Z)jzT`l6O_{+5=vcjP3 z-N{h3z}t>mQoVQveC>Km%XL!_cw7E>G&)$hN+Q|{PBDSl97O?&UTzDz%@A+9^v3pG z9tiG)SGeK)jt2FORnQvv!km@VCF(+BNHvbS9~DLx&{O@u?l#)zdhUh3b-ml+{7r^G zt8Q%4?4By>2_-G+86cwiuEjZk zykNdy${w0fcIMrs|F}Gz-3|StT&KLJooNXZUG20<$>|a>_Ex9nB}!7c;5&!S1!cof- z9LUur>$`APO7TqY0Y2$P^B1x+I|0beEhJ~@jq`ft&Asga{WVnTh&)^3+{!d`n*P4w zXPP#4V%7N@@dlk%XI|Y@G$xVS$$#;^J-!waM|ZhRPRsER1R?(5Tmv;Tt9w7em;@MWJB8xOSbgDTkU6faiuxLAIOLYHib<;bxjio?d&$So zSXhKL*H4mfv7^7-010KMf$U5xDU>gqkMN1=86IWteB#K|sF}Rirp{dUm751fx>29` z)3SB^^CIJ0&s>{afIZv23#lTK5DR4AQ4!}3NZUX?vY~z)KZL4+$ED|AGL+*u&kjFg|@m`SE+tnu)z94f4(MO;M> z-H~e8@oCUP zXvhqqKCu}&eZk}t=GRmzFefu4eiG3QZA960y-KHe86T|>R59Su-m(k=Njml2OHFma z40hg=7&mhh9?T@NA0XY~Q*6f1PKiuas`2R@0?<5Io`Q($x#p>BvYb4%%`7YYVNgp| zT_JGU4p9_R1z{@{%Uml%W%3ZN2=l|0gj5$;2c4=uDMZ;C`LdQ=a=+3lpFJ9D3cAvs zpUiyOD!hT$b0#c&@vi8Nnrum8jgHNH#hYx0@#}e&MfXd)M{}3Z-&)>@dX#nmAGk}q zh2#7m@sDuLXvv^0gg}po2agI0o1){65Y%s!shb`m=aWbWgX!#-(p5_Wf`4k+& zj(2TS6hcmwK9k+8zdR7Yr823P!=qVoiA*TK)kQSD(Y|M z%pM~?w5Ig+BU6G~Na7q|K~=PTV;5AH&;(7%ts?FQzLoP6e%mLatM;C zZW=eraZW83XT&9vMYLxtd$kh14vsNy48zJb1!gU`MIvuQ+`;yb$7Xinz%C_Rhj41% z8=fY|*XCa^hgNA(gbgMv2uv@7US1Q)pa|KvS@a;J75=AyZ`X+H;0mPPk-W8>kSO7o zYP<0FQZ8`0%L#uy>$M{XkKdj0Xn_zbBt)Ew^+Qh@nN|T?UPnH}UT|FhQDZKV|4Y+c zOT%Oj?cN@rT@wv6C8JJ4vl6sYqqi9JQe>rU*wloN9lL1(2(EyMdY2~Wz}YQ}n1y?{ z9%OR}s2G0iRW|o(W^rylj@LLk+)BfrKwI^i;S;61&i}67U6q=h}G-=tXXy zhFFPB=*3eTpmohySvyeYpLN_P>Bndhn)fyt&;&4B4YMA8K6O&3$pn$qDYHwto|`qw zXlfuEU2{2`tP}m6hPV5G67Fo52cPuN>sb@BQLp90x;KZ$(=cIr$#W`kgfvB4vdk0L z@9y0d0%E-94%cg=xEbbtmmAO+gcA|2v&Yqb0mRr~|i{1X5?5XW3V(;h(FywEtj z@GM_I%s!ykZ@{Z3__?vMrvRE~nwNQjmqmiVZazCkp3#LfLb{SrcRKG-^jTspNzvA9 zyd&dB5cavm&g|@c44w&lkL<)pAYBpq`+uj#!Ot6I089^cKddZ(+*8G&auWkSyjVq{ z;v?r}kGM;!Q_hbNUPFJOTfx?^gKb&tFul=P(P>ZAA9*V61iS0{30K*=1P(Gz<%gbZ zy0h^LZU)l1bVXweW(1JmG%~&Dy#@z7PsJCl4v(l$!AsW|A1FQ63x72lXjZbAMWEK% z4I-t@Z3anb0ljFjidz`mSVo_UUb^xpnFf{P4DB*Az0l_l2b-DxPoXvubQn}i{Xg0FJe=}vbl^DgzhNo$u8wl6)e{E-t z-btkkbO*+J0OxujUEXM4&s_PZZ<13MqQ9hR$pa^HO3-t+tQh9u&xFMm582TKb+4dS zO@OStLVg7&xBqa8i@AJzRbtK|vb0a=F?S7WrkaQN#Nar>myl{pO!dR4K3PFa;O2K; z%&Z_eW`z?AD?H+~PV4ijcayf)PGMVj-Adr(7vq@1bfIF7DSwOF8wPG(ODPSB^0a?QVS_nv0Eg8LH07LrXw)E?aCk zg^mQ3s19sq&euB$(@RY@128Qa3V;;(DT$qI06OnMrtXi%S{-b(Ia_=(9X+cI?LV*y zEb{sKAAex=J|W4x!LPsQfG%?w@6omTf8=nxL?utXwH9{}#J**)Pl1Cn;Lij&jJa`x zJ$=Pg>qS=TgR27tz5T77m^aMvxlid_<{3K7lOA?6xp=0LPtB)8iDe3N_NzXz(C0J$ z1aBXgJ(@nx@wJBW8u4|wW62(#X-zV_;mybcv;kJH!>xF!Yr#$PCHugLF6^aH&L(l3 z@ghV;wf_}z?FSrW#kR}O>0`y6eM9|}#c7Gsex!Q81j=YbialNz=# z0COQyO!{k+-Fu}2MQ~zz<_rU-PnpVdnn}~h1@e&1i=RiSB-0lSTxT|3m!`EBn4DIR z%_xUt=kh~W3O24F)f(@yp24qvg%DRFopN=_fZj_4(@!Fi_vW_rUnpc37&fmcvkQ?E zciZ%}%w8ni`+91XBL% zM}gfPG}apsq1r!UiB|2!p*E*W^@hxW{pJCm+>nyq6rk-)pFU!B!po7&aHrLVxQ4qE zfqHO9F+Sw&OhfYGy*h+Gb=c0ITmw{`1nu}#05ry;RSt0`DmfRqM0|b{DAA=}4jp3} z-p*ir-j1q!Ngqy02SkC+-?s%|0vylSr zUu{6P2ByL_I*<{np<6Y@PQDecm4??tD&h392cudgEpSv8IiW%wVNsU6&??&Oi`Z`I z9R*WD+y4YY)f-URYobJ1?QHhjYUnew0Rh4JFypyLaO`)t2vD3a1}vY@03lGyQ&*H@ z7b_t&b{IP&4@h1vkE%vJ(+XaJb5Wwy-cSROhorj!Bcb~{+KD3C9ToBBkRAiTnOIXO z(G6v{8kp2-N2U>zlrOXIctN$TsRp+0VXv-jmvP@9e}R5To^`RbJAvlq?yL z#iq<;SZ*||G!|8sAclgcva(S@w-YkhfeS-rM_K&PTL6SE?eoN1^GO;dhGB(MByEkV zL(Rlv=@!JcvaTH3GgzY$Bd;-k-0*=z?Br9maKggrnMxOTd*R3{hEDVylP1#T|4Pjg z{$c;|VfWC|2Ls#~1->Ld!_GE^Q^Dw1DNk4@e!jooA>S6MW#c=&cb43VLi4o6Px8(KEAcvYPO3s4V~5>B0OFm5AwzGzG{u1Nb9_IeXXi?d+j*GL1LABTxkG4X5M1WAZI`Z+YtJOFx(EJ2M?fS`O_K8E`9y?*f- zO8Mt_5f5>?CLvL`z{>~s@%y3jur)5eX8)q_&!M^?LS`(#9y43AF9=iF2MGnW#B)-t zLgADLzH^k^31K;94Mtuy*AH!y?sYg`u{E(%yi2d`7X6i4do=6TY|RORvV_JBMscfG zJlAuIs@gH^!jK?KQPF0i&~T1GHm891x<8uqZr+@QQK+@s`2>5!NRE9u8dZ>rEkW)N zRNp82;Q_ljSPv-J5067#i#gs;yu~Z-ANFm~z@Idg2hT=-K9Im3*^F1)#jziLgde}= zyC1?h-=wxU>9|uNI@7gh{GFkzE~>r3o7$L0}l)r-j-R$b$^KQ zAXk~-cp}_bYL@pL!zPGv>%F6GUO4rFXhD+$AB}ScEL8sKS;gHmWNC()#m?-l<@tQs zYuuUagdEE(IjILDvn6}Fyy1+Sp_`AUFKd$4C787hhI&B}9WC8T7j?cv3hFHd_lyx) zOSGA`tazvLa+2xYTBC>&i+za5WUY>F0E4+=;yDgqaiC%^_Thd!i`&Oayqo5sO;`*GONdS zyG`UKEnB~+XSe9CcK^=REg@pt{So{bL%s7eGV3gVV&4Cfm+D>%E)=6!Hjhh6HOk$r zTTe<82AVccT;r?NFU99tc3iBImGqqGPC{^>k*~{Qg22)}1&4>YB<`B=h$U6_r_*6Z z88u`9m%2E7bDdND=BqPG{2t|`pX46Cu(+2rqJ*E6AT$C;q6q-3qM?wJc|P;}1vdUz zx&sN%Kt#&C(ha1WgypJ?BJJf6d1Sh9Tc|S_Zi4t9LXRhweSj@Tw0lBMo*y)eCOxCm}358x?$VObXS1_06PA9uU+b%URugcIv1JD%%&zXcv;VlStdZ{l%#2m;)%_HB+_QT z(n;^NWdTh)CULT{By$Cmgn6{vfWv)gc`xma$P`h=QfpKaarfkZ5&0BUKoJo-cm5Hl zs9heQ9z9JnX=x-dYVRXOJ(pe6+m<(9RUJZ}|9MJp625#D1|q z$??7t59MCnXt^tA7+AkBDWfT)EhFHE%Xs;kG2Sz2^G~%tz`Ou5O|pNfS{4pzV@G7N zjGRXIN{J<7owS(?MQManQhaMTDbl8CTKW!yhZ2dhOm9Ys6;j!>lE&%sH65#+_Q}4My))`hP@AQRg$Mr`&mU&JNg$=d9T8%;%tlKWC3TdL1z9v5wI zb`m8@ke`64HqykeFiP=HZ)8m`6t&^5-6K?pn2O8V?Jk(=i=h4>VTWX6qhvM#V&^H!)WA4L=#{7Z zl@>X6nT-HG^Q%*{<+)_piy=YAwd#GGi z4}Z>YgjE}1)AWBJCb47d2ib#w?u6;X%W zM9*5+VTFHl4W69KYR%2`C)Z1MOrWQ&>H0f+x=#wH#KB|#8<@ew$5%1eW-Z^UB7c1_ zZddln`1d@3bb{5Cy>d8k#_74oRKkdK$Y*yYBCcck@}*#O6_K_a2K98w()gp4T)oN* zLM{jA?ythN?N6kNh(I>@^~IF-O3S3m#D_Fh#dUsl<^qW(A^VZ8MeQAlm?L%)Q>%dU zO9Un%d8yT{m)d&cS^KHDQa&eE&V~8fQqPB1pyDc@0`HpY)#~4S|{^| z5}a@^N-@&TH(+aC`6cCs(J?|QNY=Xd_ih$-O4Q*_feWl$TSO(AnT8glh|!!tIN3=k zs0>nsgT%;E5@pUnQ~A`V5@PKZdBWOBjinjAP}@eQVTAT?}cmP|1=vTT{Ig-U$M5Exd0+&T26@{#UtO%Lxum10p=8U@pktLq zVYLHBn3cEZL)mC91uXAq9Tfu1l8L;7Eu5J|f|(E5mwE*~A+wKOE~LTf0Qk0P$dRFO$+^OBFWg&0AV9Oib;chdKNkA5liL zJ#Kxjys;}7_-}Xut7Cps_ye{#)rL=1zQ`hFVf>4O0KbEBN2*PW6-O4{o z`z2jCa~3R@wf<8!`Aa}Ua>14)2Z3a8y2Kl!xj799{TKZDS=(cNpDv^?2TXWowgJsM zBb&d?RUnvnUUqM_33nqQtF^xbwah8vAJWKKC-S(sZ8aQ2`BISyh%%of%dW4K^KQ+pYO&y}gy0W3eyWx(vo%4)>pbSh34V&3$(Q`4#txYD z5qX-sx-w5)9W)&be=<-;ty!?)UuB4>M(_2(SRA9nZi(Q zp$uBM9tEAe5fK*10y%0Z!r&KRhxny3U<{5j0>sJ%`2_HtU*4F~FvvADJQovfs=WLz z$pmBFtz?gUxJa#5vp+_+wIXk}MV7Fxq77NR2jW6QW4~Ci*p6f8qx#Rt3;zI)_hLYyfd6v=bMaGo8`wWgE>I%m z`F@m-fS@!)bgd*|cTv!%$;9SvV?djXR))-rowa(yD&k}mgw0XVd+IQ9f1sF}vUkVX zUo;agoHxTSaDUD2ij^>44apNdV+me1bG-{GkHpbYG@{YKcsLrih`gPm?{C@VK$Sm1 zBI*@NdIGiinran<7A?!$1<4o{!4AD>Ar2tjO~aFjGk8vMGEqs3G8&4V`Lav=Cw!iB#&qPzg0-CKgdW*lIlV0l7=1 zjgj-gwq~^Rhc)E$HtYNdmhmlkzf)Bax^TbfEXWH_VSpl40{XxwE7_a7)!z2pjXT=EWX^& zR!@Z2hB8P!?hMYPrPDX8SB}mMN90hVVUTJaqj*uZ~SH<@Jre1E9-9s&_Nc&2@Qpr~i+`|!GL zLvpK$4&sC#tHx8WK>T};JIXb&J7-T4M;$LvEtvWR(D@+}w77vNb>kn)3sU2W;`7Gi zcBpteWV#zlzu@!wKJ`eo)&I9Wxn$1zPb8cjFzf@@`ybn3%Ywk}(T!6E(^JXY3;KtV zQ@ZZJ>tjKde)u^=AOGuvf2Tg*%sjomMFpR(9;vzoqAVHR#n%%E2<-DB?=(=@@GrY6 zmm@q7dO0$o`6X`E5@<+r(K=poyJ^&sDfodm8E*oHNxXRr>U{pn? zLFG~c>=}MDYJ`>+gcMe>w4X1p>#%ROx=*tqkcIpY%FeM%6Cg;lUFxbX+qP}nwr$(S zTefZ6wr$&Xbs5{UXFkmAm)ZFXnJ43%h^3g!VI8zK+Ty(tAmD4bo(dK>8DCME5Eifl%OsaXKVwC!Ze8!f^ICRtUA^DWt zU2Ljmsb{>8Vw^20EmA2Pt>MNYt8jK%nWT?|NK(+yeL|e zL#UDUkEw#PV|xuYr-7=@u06sSsrBz>`)=*01J0#8VLs6z4_KgAGUjAoNt7oh&X622 zlOLxpPQP&B2VlbWTKFPA8MuYWCzy8}9*N%4-g&$=F**m1ulT_y#@T#6g1v8y@dJ{W zMZLCE-TjwEy*Jl)F1!-IyX+^*U8&mp!Y59?fYEU|^+PrF)77;~kM+{G^(D#mTADq7 zSD;jLt2X7$K9dbn+SL{ZaW6Qz<>v?IYto#2pKvovHwSgBeT|J5jsl*+#}=-jEHS{)txw`40yv)1xE-99G;|Mwl^x(aoW|6`TDeNrQoXP& z17A(u-~@3VRA34@7%glk7!QI4Vt4AS9nVS}s%1LdF6y>kkdCZCT=yYGk0M9MG|D4d z7NmO8D&BuY?gP~WBkPkk|4CEMu%~ioB{XNZkx!Enehl$*Bp#E6-pC^k4ro=HUoF}l zks0{Kbjff$vYn5h!eCbwoR|DxD6`$`FMVzz55Kcq^_^vsiD2epP#?p1PLB(ni$N{S z`|Hd5B|!`qPpyp_6dcfB1lD{ZA7C?vQ|GOd!j@la4h2Y-B(a&HA}}1l%*UYS;?VL4 z==g&WbwSGt!L@-blg%Q2i6I1F1Hn=b3LOJ~IfK7r`X|j=w%#$I@~741M`XHP7wbC< ztf3dmzyYFJ21j#fm+T*h6x`Xgo!~UQ!DJ4p_A}HJXnI3Y_jQL}F*$>3r+-Z01GwS# zOR$Xd@%_+~YNB!zD=FyIly)@m1m>^td!Z1+aZ~osy$z^#CeQ{(qb5L<6)DilRcz(Y z3N-V2Vp;840^BDNHa3cU2OukV<0vsihKED+5(E+9UOCnGe8L3XVeh~nGjajFwH>P# z8o2w6$j70`113){@()nbOgtywz>S~`y3BfVN@tnwl#wTRvplL6Or}M&Gzyv{(dFEN zsmMtf@^rgcd1JBU@Cug&+@nzqXA2?QN>8Be#VAvRnRPZYZj3 zcBFfH(s-e9g+HXSO!nF3F`x#9t8w`NX%FWfIxm3v2F3Wapgiub`^&32mODO36JqB# zT0OX#R3fgR=jO6fvS;c4p)=$Mels{jC$NObV4Ij*BEN-`?>@xN4+Us4dbJMa6Qy!? z#(jhIVjWXk<42qC-{keaDi1`xJbL-X>mTXDm3((fJ~SAX=JxC26oH}F-~2(uaxch! zQYef(^l_d^FxlNZ%qj<%p%+dPdN*)%43ij z(=3+#OcxRcgAl@7CEusrf5oA%w(rE}c8m=wq ztow}SiT8=*4CG8|P?g;rON=}q556TM5OHsyct7D&-9jlGC+uy2H0lyJ`2s|cHC#v7x9$O3^ z+p&bty2FUTrHIeZxE}&fd3% zVl`#-N@Tt{NZz$taPbKQed=@oa)*@OKb|PQfqVeD1)Fc7&ft8}r9Vv0WPDODcd=&z z-wZq>v-5DTWKYu^fHCQeG<;bL@0{f&l$BM#YS~6fwJH$FAH{iBt+S15 zp-tP)>P^*ar)w*>Ya=(C^&dA=(qQ(oPQEdY)11fb+b_=XNI$=42!E%ew_mKX8w>*}6LC>V z^;+e1#)*_LS}}0rC|z_bDdpbLb;k^vLz{n&57}0ef`V-0NsNd~X&lnfBkFX+N#*R) zb;at;MVGSrV%7MmIucWtEdMEJgZwE-gZQkyGU+jmY3<%1jk z+9-mu1|lmISIeALt;ZR0+EiG;33bIJW7Vq5B8uQ@1RKugs|JNP#m;L*-nOvfq4;ab zGR2RnZ8$o>?UMRt+cnaxx29lbbkoM0mz+$SN;o*-9WvoG;o4TL%gMEqW{f!P9V*yp zCXMM=$HQ1opo5xB**fL0Y@OuYBJ^L%5SViO#SQ7sF>Kch({6d0=M$xzN}Jo(I!0oI zsZ<90*YdpaHg1oTh}kvxUCOshF2oDhE>w@mwb}3}U|}fXE7Rewz%X(h?cS8xW2KDe zAry)@>m3a7GEFDRl`GN-t)M$I!jv@VI^8$dSIl$oGZi)6koKqp5p?t@+!a6^*6Yvyp(F1YtpCS7x>tcWsgt)a4!QwKSz-3VQ(i) zHMg~GJyIoyqAwbxQ;TUbUl)tY5Ggu>`7Td7xE}t6QrI$yST#c{^e${2JSdZnq6E|- z9qDF_xscvOw6t`D^x|6{O5?>BN62y6vX9o9(=Bh+{1?@Q814k?mh%{wD4|j_IXgMGWZAM$QK-biWvR9lXdpB)FfaMaRy&( zIqE~Adthw?19y_dYiBdf;FQze)(W;zMZ`2PE@s=P)JmJNI&AJHk129rPz=^OgnX1s zZySoPJ=}P!x#hTT371Z!O^`Ol^zeJr2V%&afNs{FGB#xS>xk2+5 z+7RbcJ1P}4s<{uQkP0W@Aa+b?wRY56W|i$AVP>T z$eFP@%V#p8F$RHL`r4H+oq0SXy=3b6;pX6cYCb(kxwu0GiAG+6IYiz~>I`_;$g(r< zJPrb_Ne1~&js_UK8XJ87tC4;E0HPK`n z5!)n9lXsNuVQe~02A`_*F;M$*JdR@~QS0Pi=O*-Y<-Ow=Z*ex#9w|e&J8s=P7o&4& z0)3ozA&-~Q1Y0S$&VmE@7z_AO&h5_;X-3nB1|m09+K%Cii#=bI#RwDZw>tS$xAASD z_R)B+V_s7HWZvYRgfnrH!`}fDxT|fh#-)O)5 zohlqL&5Z8nIIJSK1XZ)Rsa87&u}bD!3%^)i(KL~!$s$BB+Q{Jh6wgN~6zUPnY^ z40Gypqq=WRM6qLq6`Mst*%ikIl-3<*{0YOAu)1ofc#E%?8WD7;af(qU$4pT_ZK?nT zPiy2tSYc|9#%t&qL)e~JKi4~^F3C}xi*%?CB^-(OZf{jja?`E&+3{1Hw?N7ZvDbS2 ztMZ6wz{Ft;H-Vn>k%V_cQAVOwOpsnBxtxXS8rfz9v>hcUbi0jGCYW(A5%`fsf3TbM zjmT);qBHU0n|sNm4A%qn*sZ|1OOc$)OWYHeqxkiGRY_*(Q5}(<;=}BCd?I0^e4#At zicNdhro?swBP?wJRTB&zd3`{DsjITf`VcN5zZ1p%jISL=H+D`1!=Pu!iK1wP5YSW95`b49ww=-wM=~HX`@M~P!ssiQG{@n+DW$TBpF|dHWY1Liz!9vSSo@G0l2mFr7fg= zfe(T0H!0fnZBaG0mXwzQM&KF-9t2;eSS-g2(Ho5GfoO6bses}o-px1Z@{Dr2YR7fK+u?Ij0ALzZVgM&!= z{RU$jyy{X`R-XIqO(*E2tGpn$v{5|2^w#vi&PDR@T38)kyf!$aw}ec828Bu5o%u;qRRf{*6jMEk$({GoYI%~pO(Lf zeInfAMn$|6esA0(`~cFa++K@MU$GQ+d(>Z}bhFyA;?><7G}!C!G_tjX+mWwYJcfq)L*%s zS{j{Q!DBJI6bx%>Uqrk+=?O1L;7(tRo^26f^x%u3q_5(0y`ph_V)HmIqF?_g;Dybp zVYwFaB9=wn4r_R7pUd40x0SJRm!dhjB||ajyZ377$zFyUM{`1sMnn(bypv~ik=~*s&NHgG)xa}FxF>iy}3=2G1|-i!Ra!k zf*u|1dB2(AKB<$N*ZGah$&CTEhLnxYMrbii&!D+!9F5i8W$|$*z0fHNOh6f*BmySf zJ|mPGImTvOeWbBxOs_P=4}mtVJ1iBPL2?LMT?c{w8MtSC3AmEsKGg*0aPpGmR2u=D z=Z+_NR|}rnU!&|RqojM0ZL(I3^A zkgCl}+5s4Qn$jb`rNsgrb_PC|CbkY4@tPUHn~(}%B#PQLqO{^nYo_BgW7^4M#pY!? zw8UMgbca6f8Ex^uuu0H+aq3h{R~!QJ+?glXw|a^SSyFG zDK5Y06c%?|-tTZOE8W-MNqek(z;|192jQyp_Cr@PU*rF>eXbo2QsIL0-3#AS(mW{5 zp1-D-qSksGxNkSY^Sv-1qUE5xCYOTsJ{R3#$${_OIq$dTP_KBk9Khvd-ib|*DUM@z zBOBGD<(A--Hr8+tB&R-eW45_NpYBx&jKndHKDNVl=yYAXY;m4ZjKH@J5ljEo9;1 zQcLULcqKL1n<+kouTCxeH6`}_1H2M_Uzu|VQhMiCVGGcFF9rng-VyX^+7Uw`P6dk1 zh;m3+q%LLZQO_l*iuUOFNc)wF-iv{(XJPcY1g#0aSmf$GXXsRCD?r*fyL#lOtlk}9 zD&N8v&>2l$XQ@~HaFih{?@Sh1!@ebJ{Ab=FlX(NR9;NR$i5j7XZ#79*wxyHyVHi%z zzCz>GCq<-!T1B0#tb*t+xPIUI(gaBpe;ct2C7LE^5bw@Zm(C3#So&yV6V$43L4MuO%#?XnmU(%uJLGs zd(O|pNBxd9Y|9Y|IvG;Ji#j{zX(Po912yaE{@kUHx)Krc5oco$jn}|( zd7oRBN2m^KxNW1=oR6$ZncFu-!TI)v1F$JCovHP}ZF2>x&fa%t%zl6W{kjYL7GRN- z5j|$kcF-oBR3^;~6u})~R^hfrU^gTn#En9uBMrk_B=+a5cgP8*7X$1QI@s4M>qkS6 zvOs4ctQfr4y z=q2v~6qdzVvdWL%xd6uK*557c&vqM55Af2ZLm3oihS=`po;q(CNUVPSrf{L@u@E%G zGlVGRbDACP^M%^opOBmNMy6x<1j)kdbNe$YnoiMzF3ebqEUfJ_3mRYCdqW8r zRSVml^l-JIYhiY3%ej`3aleFCvNSXIbGGGcna6mhsr=LH2e3fSGGVC?RM3bs$7(q< zGwe(^0zr*ZqNU&dI0Bwn@TYu0CV(@W5J{tcR3L&vNCXR$BDye%pFe9)vSuWC1M(H` zIY<(AIZ^nQRJ1Sd*xLkdyrWz4ANJ!jq@WyoBrN`8ughM@==+Q9=|EJJY%>RrT1lQ0#YW$Afxi6 z<5U95)4(Ks?y zE8ttSfqbAZIQe;r`}M^0>K@XM>({j;O3Ax=w||ZwJ&> z^XdSC(SQXDY9@GdA4&I&=-) z_j(vu!=F_9TgG$dz*(Z8#~dS8C9OPRX6^k^06#8vTW3RP0NlGA2$=24*HswDyj6_9l+b7A8)`np$?7V<^6}wdm|{R%nPu zT-US-gyhO163H%COOA-3F$Pg%@yr?#g^uD}JKNtczNb?m$RtwRs{TlsSx&vV^NVD1 z!(1L@WESOW$z@UF)#{X1$J!bUi|vv*+{5X7^J1SqPp;myGb4lZZ^p#mzOD?P>)rj~ zaurP*$aKRWaApU@93Ic8Ke?o%(7w&`ge)S(5fhM1NXvp;SAr>$Yo6~i#lkprN$z&O z%O14Dp`IC+%30^iD5_wecW`?Dc9|m&4{E;rqVlKlj}oMeUZwpV=x20F zJPH-s5|xZuK5*CHYe-~tx?Se}qaiiS`g)aI$(bl+?#XWT2cPW~)|6_Hu_==sbLFSD z<`c;jZ*cgic+%%NrNs$F8|NTKTf`!wm;+PP&Ft8?2u^%|!-Z~fvFO9mkJ{UuEjyG| zlilW6BbkC@8(CyL%wu&Q8U=I(8uelJ;CMvad638cmPBN=UQ_+jT@aX^-h7NbsHRl@ z6Vn17#!f;uM&Np02paEhzf}0EP46sei#K_teWZffZKI*0Yk|UAg2EAuPVyKz>U=;| z()3>z1U+p)3z31eg#6~FSx5e9f}8CH+lM^@t+?%xyZVo1#HT@M@X)WUSYVC==A)yO zZ_=ySLR&A2g81N>F$r$z->qi&uR_0DtH$=ZJoWd}f)uMA(+|Q9t;Z#TVuRSov*8%b zY+e<=DpyPno#H~3ha)DS<>U3Gy$3<1J3@z)0%wx}k#$Pkq>NzBL``y_SpxZjc;~|1 z$^BxdwXG+&WKvvmaYAu`{mG<+2oJ)^cK5%3!~4vR^a9vk5P2DEQ}^f{>MUrhW$-l_ znfA!~V9x8=U$0+x!KvALq47&*nDF_fQSQ04p6)rCQw|P?LoC!*u@KtvD0IqueYnf0aASXq z`*k4?CHDz9T<2LQ5VIX*SZsUKY^}@DG^I53Pu`tSeJ%cI$vp`ekQ|&gw}d5wQ@uKv z<0rV(dCh-CL9PHvk|gKcyzSkPjgI!_X6>CK^UdBrntgtP@$ns;mL9U?(d33#jM=bB z=7{YQNVas}Kpn^|hgsg*dXAa*{{EzYD*8lQ8uMSP+Qn=e&^nFCG89UOq;`Mb4y^W+ zrm6oI=Nci@*G4F$gkqR%#D`a=Cz)lqL#yt2U=UxmEj(;%Kd>~hX!@^05HTAgR~K&@ zMxu8kIFG;^atFuY;j{5FCB+I;*tb3&8P3Wz=Q<3GXM=!T{FLeZj#N4s>qtWpWN42v zK>7qqWn_C@S6GI|Dy*hY+QnUlNoo$w$1sIxcc00iYF`kge_l^T>+?3({R({cCEgN*ULUcaV9GZ9e6YNi?AZ`AI`o!euGx>^?(DRKA_s zLl1lK^Xh(KUt@`dmXt< zKnanS9Tt{hcXx|W3x$r+;+_-9TwAyfSO5L0u6F<5Hc-VEPyDASf@UmQijD^VkRl(D zTn^$TlgA;B(=4Y4al6_@ksgV1Vn9y=WCsPM0RdPt8oqr3VfLInb9?bKk3<9vw& z7}>F2WyakGaD0~*CD?#-C%g4UL(HbYQ;eZ z!F_2lBulWS#9|3{Zpa%Wmkv7AK_~Ci zpwe&rhoq|0$ct^`Au4W3Zd~zU@Wusd5%%_$N#ULjI|l5TsD)x|1v6B88xT>5{Czc; zY}5ifR+$oXg4L1A)s5*`?#RuECyzcMBjzzIdF_k@Pxn$F*?tshWV43vf_(UTJ7`-p zyqXcTQ?@WthW1x?4(xq4!Um3JhU?mDiHpTEM_~2+jF}Zuc-=M^T2JaD5W>#9@$^Ui zeyv=dMos<+qm}iu#WU&x;+U0@s*(UJ_o&2GqbQCnENdLH@ksGZaNwxA=`MQOg|3-_ zvN=ZiU%9dmQI3q2wn=Had5#_Z1+i{VG8>y5+->9&Tv@v`a(i%cn7=Tey& z6(44AKKq+?D1wh1Y65Q@`Pnbxq;}J&l6DeER2#lXYcg6{M=7vYA9HFlfLYM^k@ubN zQiHY;5iQ3833{B<7va=gl0N1ixA^P3OH+~ibkSV#lGBzjQrN*x_zwDf(V*6F<-E}| zo|KLXh{T!!?_n%avvHkQbzxVz3ounG`-n6Vg3Rfsm$I_D%Qt%TZ*F&~iT60Ewy_cp zdV<=Ic5oYR)h=AU7=RjDs-7mNUCw>5Ih9V^*tqlf*C_}cCSkV@p@*s~r721KnebKT zUH=j<2N(t`_-^=vi1*|amS^?KTGEj7$RhzJfvYg7+wr#LpxX@#WfoU&&0+V1{Tk7S zb7g_H95Zh(rcTd4<`7x;>!n5P!@Vr4t3uRT=N~whbm#ub0*o#)Q>2~Fr_>6~w5nZ0 zb!qgq>zvG2hgHZUSX+WY`-5J?agu=>;V~{b40r;q5~wvBw1J@H&f2P;s;wJ3>c*d!+MYxVW~dJK z4>s6!>WZ(8@!O(puwSun(C6{p;ZWWaJ<4>&_EMLobbAk8ZGm^0cs-K*vfGiTo1_VL zIkEN__2GqHC_sm5m^ZNUN&74=&?W+oh6m;LO?29Y#Tu zU%Bu~vq<4&@w#BOGNobxPR@xyWV(o+f7_V5%C-sTH!^O162^CZez#|tX0B(L`L|Tp zxOe)W^kPU_xX1pY84QW9H2Huvly;TjU&s&-Nf5VFCD9R9`#c8q`#2oso4CVOABuP7{R*_p?fbv@0XecxOp zGtv848AZ#kMOd#9bV0Dy1DlrE;kR+2yKMrkY+6)Dz8Iz3iA0|M5UCEJ5{H`V_xQgs z{dSLl@LXan$eacdxB6U47cr4Q3lDkRdN)y?1p7k5M6qZTHQ8Ob0D3M6XMM_u8r+U> zUwxIQoWf+eitqRW_K^Xwny6sUaAC(CwVqYkx;R`S06q=^dujVB0{${Dn{wZqQo_JggFGWvRB zLHx$~VZa`m+bGF{!s~euKod14=GYY;h=|cB)|ovRG(F0`sd6z$|eB>E7^Tvdn_(GQ_i8^#%VRy6 zpN8x{>K-S0dH8f`1!zLG-sW>&nWr&X$E=`Z=(SDu?4V+F-4DN$p2j*Iz3?Vt-P_(- z*k6`ZZn7OVB7|eS>$4*O=8}534wwW=<~f4(OJ8pXoan^MLB5Ea+5Go6Tj;%$9cO4y zdf*B_XYgiP0O|Gmo>zvYZPzau-NCe~E+|S!A|{z>&Q6&7j$3mQSe$wOgG(rJZ3^T~ zJ^8mb8>drx;EB*IQwv=m&KKFxuD$z{1Y|KsGzzH7-0E^aX z;LSk6Xg~tyR$F?(Ff>A3SHiU6jyI-PS!q@;u%jK!P1RY%7;-%c+zpa3{^`ddELvV{ z;=ji6|FuemMY7YO{BsC1|3d__|4)6blevkt^*?Wlt&^R#iL!~ivw)+C!GB@`)&ICF zFQa_hC5&fE<4Qmf6VL+{fRchZK#;dIC_@Vn5eTf%DJB~{h>HT!9ZZ3TEVZguD$FYl z%dtd3iK?-Zp+%8fSGGH>sy}Qm7do0Ot!#cCcd7{HH|Tb=+-`YJb9_AL;Cx&*eSiI} z==sIdrrGBTv2=WuwT+*~1@gf>fK}E{1$4tIAEB96j9=^az5BW6o>isJZ?sEa-Yb2SW%-mOf1Z#SIiDE~u^Map1v47mPXL8{0ipKmV zVoF2CnHoG)`nBP!%j{9k^#{{xGT))BHlIls|6odV(KPNU&1mUz-Z{0jb;jd zrC9IK4sp5j_jNXWHTw6OyUPuJVDir0 z(YI`2oiSQp-g=%VZ)>I6DAs+1L4ZYhhFDDJi-(%&oGJU^@BPiX(z%WPw>z<)LV^kb zR*-92gaGA+L4At|<1-aDExDCb8iR2eMxMwxE*ZspppJMAswb%r+t(2r&?Z7u7<&On zdm9`9GN$n5_|6+RV@?>lmg%=w%ZOh&j~x+=x81OecNzW!l4F7kr~W5$hwwDgL5N7B z|HU)80p8UQ3)lV@gu`@t7m>5Kifqlsx}YTk39Bg>57iyttju8v3XMn8*q)JLnM!rU z61*|q)3%Pstl6I-#B%fdQxvY<(6W;930 zaIagJT`~0l{#DNbd0dkWj!D#UjEUuwK4W8PvvtNaz;FWGe(XVnbBQ7f?U?RcJg;g! zV%*ug>?}I*Gf4RR3ricBp+F%>^0-5|PP8|aup!rYXXh;37GF;;s>MC#p(WBvI8xfh zaZ{+LsEPXBgFtVUlZYH>8U|e&g2vK$On{N4p)6IMy?$2x7G}t3%MjOyN5cyheLK2=etpeHw?khcOhM&I^*C-wdCaUNB6};%0_ zIN{*zqT>#F7T9hhYLT@@?K0-&z}_^_%-YoFk%^);45 zIpKzo&MXq`&MK8#85vcT6a!7NI0aO(850sO*Io>rk|l4WC9`69>fZ^TqI3Eac+Ac^ zCE=6+bA0IC2QV@mmR5s)2`SWR8*}5Ay`FZ5Z$&E?=}W#~Zjg7Xn-Z~d3AgdDjanR(WFbNgj-BUc5FEbq%MPoAsio?$mquVN+d7PRmtuO$ zp(7Lnks+)TV*B)*3Up&;4LcNU2Zl;fDJJ#F@bPN@8gte_oO)TOg9bG#?s)icS{WIk zSdn&{$B>TTW**dr;D#U450__r>Iq-70(wne{i2o{-gKaBjme%gw7VgH^td-3?ig3AP!bih0?kgU2GQO+%;8BidNxWC^hWn&T?mTERL=bGVD5ZqCaf&!7$|b zB@kwJUiV~W{pn?+8flTa3qfW~f_#O&v-{VN;x0fO)+L)Wqp|l+S&@41x?wbJ5M1{4 z=fZ3p5n7#fJI<#wNnCD<3!)eE08{5f$@9V#97q4ue6bAyUAwkIV55V54uo=&>NR@ z*?x7xx8Z?o{i z&{uZMsvwJ*gm9j=q3ss%m@ZeUp_oa8WHHJIwZ=KcOy~-tWBHV?wA7%^xivxzGt+@6 zZntc4S|h{hR4}HCGZiN58%C{kniwNbhK+>wh%HYB>h5~z&MA$9i+q?yz%)F5MyV_AGpvc!Fl{s~Yw_RHD#cf&bBlYxESC-8Gi? zQC!${Rbbp@n)h5>2zTTSy2@n-wJxl?s%M6|EU9)>R`+8X&?()+st?+*kGlyZ9 z#xvZ5-=%6!6mQfU4IjwYZ4GUX)C>%5lIo@g6rWFqbWR)@58F9oPrXI*svePGegche z5`|*c=P%9|j7VOX8gW%rA(JL$Wm`)d*{{Fr=OFkBKKM?g--1bAC@Nlg&Iin(r_eBz z%6L@(e#VC#;T-8h{PDRyG78njIR|QAFlo}S7 zDG@Qqs2G#8^AztrB?T%eLar1cZ)IS|o3m{4$y@Zy!8Z-fbGqA0iUea0O1nJ>HAVDe zSVgSR{Qfh)oMnjSCq!7U43I3MIk9g;P9;%ypW*>e>&n~W_Lq?XcxwelA3Sv##!Z@l z(5=FHzD)?wrNVV-vz;B=kS?qIfc^Is+B{_g)PE>~{sU6a^1o^|)Eq6GP5!gbP+XS; z5rD56-_LMi!M*SCiBQl!0KA@$nro@ zfc&t!Lli`yzKpO*j*rFKwk3TBKoXI>d01J75@29V)2lat^gs_(_?b3AR6bQ&sRa*Q zF<>A641Q%g-Ukx6_l{!Rg_SD%B#<8#fqp==Yqp=z-^DY+s_~BuMA?JV0^+RW4v$n$W63%8IEan zI%`4=mb5O<+$Irxts!H~{J3;CIcDHO2L*xp907C{1~4Oth!VSleUfw(a*EPux&lyA zFvXEmu*7?YqBRBtiXc`YR>Mt$0Ic(J$?YfTzso@G$0zDujYF!Y;2mkwui3%71hbJZ z#Cr&rSL`W(wV0c6oV=!YP}$m}xWsz?ix=oW44i!J^SPA&?p5LUuV1YH`@8*5|3J2q zj@*(wJWp%qq+q!}L>PVqc}FL?2*11lvg-Wu-^f{fhI;DlV@nH(O|ZkpThi}eM&9@9 z!hPZgaCc&_N=xasU=3w|ipIB`N|{clrn+A~W@~qUX$y;r;B-{VL-EAmqQozp5Ekkt z%i|ULil(B&)L}#&HbBCtDQgeQV-GrLBb7Z(r+$}NVFG_?jMAJ<&QMus0KT`>S-P^Q z)V#O`N3bg<_b7Veh8zJ?3aHG&tTJJ=_ zLE%AR#Acuc7H0FvWz&+I-tyYI^xG6h{e*HpE8`d|QTviRp)+N@#5@5zK4sG#3vdz9 z)eM9&!hn!}2wW3kL~M*njTkZQ z+9Aakpd#5S$V>#`5}( zopHp&*(Jc}+4;Sa{+xeA$TM(-)VIj1u~jBnZ1Ns-JWg4XesSl|oc`g1F>Y3rBquG) z;&b*P(4lS)sK7yFnPV#(3DE(qkK^Ar!$jmRM31qdTP`&9h_=r2gxbJ1D7Hch?a3?o zG?!K;loM0RgH3hCk?|^1kf^6{20PA%bENzH{ogCA@{A099oVm5@BcB#`Tu);BDSs; zj&`;-CbrK1Sy)xI+>lg|zhyI>6ULte&83DU+tkGqQ^LkXv=pvHv=*A?u#izo&f{d$ zO%JAu6z_m{ekJ4O@$u`rlhfKnR*}31TD?Ji((txzofzg za$=uV6D)BY=HM$YYO~I{wbXVM5XFQ7I#Y+JP86jy1&Vi2%l0CE?_ zSvFu&Oi!U=Vuu&AZRuW)P)gH@?`wgGHYbBy?ukVDe?YGSiN*Qbz8WhE~FoMW~WSI|E=eh+?| zS&@N#+#w9EP?E^TDcy1I#Mx`~qj(qWDS4OdIccld!-%0^k8(lw^rb@f46Gvd>?d3z+LE`0 z+mU#e?s-8|qVLB7eX|D$0DM?nDF)*)NhLidgoPp{6DSl4Gi)j?c-bnJ$ki+xSj@DW z$!(F|fErp+y*`g7<&?RSC)qjercDhQEKHF$8cgSgrXys%Nn;_cD_Q&p{;}9aNz`2} zhh3XUD5IO^#w=4B3A?-q?H$~ii}Avx%!&Z>lHfiu8sghmOq`l&z%1+cWTT|BFwrt3 z=Sr*U4+^VgID#P(v>jbdiKVG8_wnk;HfrG_RxDLwBhN-=V#`e|s#Exwv}n!Ae|U>q zmFdY8iW}zQu^-z^%Bj{w-2CZv#4g|mWba$Fx~}u_n)#|tUM-4*%}XP9PR>&l#eVY7 zRO?`twne25c)86Ct?p_H_xp7gK#0c#=_D^*-OoAr8{8x~!+rtkU~UOWpD+68n77Xm zP6gLu*}oQP0%^rPBE3Uzm%)ow1fqjjAru7t$=__cD9;#qJGKfBi>6;T3NP?@$VyP><`Bk&}4g?>V%&XB=4P?K2U(XV~O z>|b)_efi5i;K;|#fe<*v$;NF6^%{SJLZQHhO;~(3}j%_>H*|BZgwr$%^cAT6{z0aAM_k1}sRsDI@ zs_M16`@Z_Ve%D~|EdD3Kf8PNRlce>^f6iXZKRdwxZ+qH*$@t0X**<1i%*VU;}qXl2u6>n>JxNGcn^~ z!2ty%Vb@jJ`7q?!NjJ?!o-E>bpn65#CMo#dzRVq9e8bEj`MI$Z5v>7Y&1bgXH&6Iy zocx|WGQ181elUo;Q7=uAc$m|>5AM7%K``BAyV_WdyBjd_<&wRBv`MJP8PNdLZsKZ= z)PJ#63?{N1(5!ERBS~@5Q0&Q$ij7lXl+8XjFy5_6^h9C_0!U$1j?07y3 z$ug5h9mf!DiNUUThuCJR2-X5Ld^T@xi+ALO_vDLlQOeD}s*G}Jg;KJbS2Z1DI2y)t!tYm+tq8!yx^EMNM*PvLuF#dc%-*gX>QzZDIJ;drIJ>bu+Ye=f2bjn(tKXW*CB1J& z)tqo26}#1`aY8as4fV_=EZ-pW-h6=j%B4J$s@4eKwIg#w#_lkV$X-M zO7KM-D{FluhZu4ba92tj_c&^q7B?y3EJC)VsXW<;QF6efLFL9OC0&|QZmc(Wu#tjw z5&c<>@5Qz&b(_+h%i+(!BUI^1gxu+_JE*3_z-&++Tf4z@Y(Ksyc}c9L@+0P6-6^o- zy5n)t?RiEyn>`sbNI+Tm-AHUdg_3MD#k9j0&)kp)Mwyd$tfV}>8y4}(E0IxKR@L1i zg(U3I#vfWZGJe5w)S&+h)>;_V9YHnPg=jHT`D>1%y)!ns&iH9KF_qSN;eQ(m?L>^^pol>49?Uku`q%w}j}b=q#e3)VSSzp#r_p=4&Z3FDT{*Gbk_61Ou#%2#~)j~hBh z+Z&wO9XORv{+SYQntIOQF!$z&C-+pt zDf>H@Ry%zjL0X%T4me)aG-@!W zTp0&Vm8usw@!f<)8Ul{R!Ywejr#$J6=xLUqH%{0+IUH0O8h6>+>+*!7`Q&5&MgZsn zKvfW|K}3GbJ&1b@N(%;nRV0&b4;Z()fu3rXd%uhSEN(=<%i~1S{9A5}!DH=$ZVp=J z(phDzaVjVOo*V5*0Bv3IJX+xfRg`=s)nCxe?C9pcm~<9!YV~ij(U#a*qHuhJ#C&Xl z#2?XzO}vuA2Tsy!Q?R`5e1SaSzE>?>~^vh+A|SBoN+kMe(VO3EnWT%_zmT zv1G-LtmBeFs)?%7oi=!dK7@=}%#|*>c+QOMBPaT5&ozp9t!utgk0&N=b)74 zUVSVguM)t9!G>4A_yb1i9b^cBhwR|r1_1s6(FEm+i0lE=$Nc2(7}VYaTfc(h14rcJ zCpOWf0(13+W8#TMJPB$I-w?|%)qTWF+R(4BlozrtQ8IxO^rQGzu>U^&8gt62;LJck zueLuh;QyQH|F6j(@`nBaVW2&?J$I*Zq;=Y$fWRWc!XT4F6H<=*Q&vC>V1ose!;XQ0 zjLBxE5w*t=nTrO?U&R!>Q(cKkUN?x7q?ol9bpULk)${}6jQCdS%Ub<{<-kJ zcmB;A71iK#k1K$6ucMNEQc?!%SpGqeapL5_4%*e5h>?CzEHIULA?Hy?)pJs!d5$)*K-*;vDN1CDi9x1#~Ih-j7i3rRZIm{Y$)!$Y(yOFch5bU@^R8Un{9{CW>edXB-b_jvk7= z16Dpma;lRV((hAz+ozAKy7*s_?OrByJ|d&^o$g>TYTgd5c`sa4zJ?WAMm>r@=~Eyr8j?Y?^n{2s?zUY`~CH7A{>*^hWOU+EFP8x#V&wx7ok+(-4j??v>E zYjnH^F+b@vzI4fDU*mMn|9rC^QGC3YDSS;ZeA5XW>^t>*2>Xr=`MED^=)5y1e5ObF z5CVj-)v4l1IH-SMMI|SReIX+yotwtTy94IsxB^|JA3BG}lrl$Y)H@0c6(Bj(k7dL; zFo%k&Xz!{7mnGCpYWf17>Q4h-WnX{f!S{>H30WrK_}PF4%L4e>!u@1?_OWta=odQp zB=jmEoE)H@6PZehin$j{;2+BJKG-Hp;7_Xe_|@PItiYy4Lt0C3E2PzioFwi~DCx!D z7m*0HW9};I&L!z%_l+{kV*gbbFS-l(RQ2l|zKQuULamd(hz00oj1JXp@{FmD+>PAn z$PNRs4XLUyiOC%pwU?QtI+m8n-$oI;CW4Wt!k_F3l)ip7+frCBxWgY~r&mma?? z>ClE4;bS~_2-5{?(=jfM@i)yfgjyJCM0ua1_S9a+4e>Vxw;&OmRNSPVtM-&CmN+3C9X)e-XYq{J8GP%xs(Wfo2{)LH@!#Z2f`5fbNhgUCYN!vI@qq!`v;)Ma~T z1=t4#<;HYXR2^7OPWxwZlT1!1F?G>QbE3q2!_wj;a&vF%sy=cDjzVoQb;GFP*1R;4 zY@grH8{{_k4#( zyff7MO_289$(t}!Kr0`Spu;d14_^S+`Ez)=T0h)d7zvqpplE@xIT$oC1|AHzELarU zX9rSyHsDdP4y8z>*X|o0@xei^6y{s2pkN|twx}zv^@#^AVJ9r5oq#d-;=Rf)c1EM% zEF9$X;ihfFh7wacGX|TBo~M>Q;WqSrA+mO+G=O;+#UE4tW8%QpUPuieNiSfcP7U&M2+VF8pt)N>h*g=d>B4rOE<)Tv25F14_WNpM9OXfCB& z4DPd+0$AD34_}wsxguC-ujX|+=#wKWv$~t<*Y_nu=a8kUOuoj6(dr#abNR6-)l2dt zpj_d6d~sshJY5alm`HjcLva z$LMTy!F0dAZ7J%NNCZp#gCni}Ou7Ex7TTMcOfNidV5-vUf~;*=zP=v_*8&WF#p&A- zr`y&)%O?tph8VxHrf{0sJ4;>r(0EbE*}x zP1v4+c|3w$?EHc7T#PEfgXq~L~CYiTZl*gZ5S}8`J~PH{OD|RsSt(O`?*&B7fe%v zGnvb(#nwks%R}0YCvyY*ZMQ6(`8cqd=H%#bl}16j=vU{{W8(J5f^PnD1}jAB5R(7a z?8TiHd{>kp-FWIf&9W_28a)~xyug~L?+(qD_XY84;F?TWEhl0H=CCu8f9rkrAQo=7 zIxdkAZV-C{)fj(`4+D4;LS$cX$3`Pd|2bdjf|0J?ovx!_((?4X1~Fi1qEzJ!NKaSG zE06+2=P8&>b;tj$bl}xS-g8c%AF$T`(4lyl1lExidUHhrJ%!sRIMMe^I@y#kny|Ka z4!O%X@xLV7WB*yS3`-RAS%)K1o*v+)#avWMmj5PGz|q^z&^23`2i1t$;+b)NUn!3r z%7>=YhAkx>816?PD3`E|kP<@%2rzVYP>}9d)uy%Gf@qV-O{c8Ef*aa-dg3?^nIDpdLEnD zYIY$8V}f3*xijh`m@Q;zL4TbUlVF^(FMEx-)Nvn!eyn2mCbyQ|%I)3+oGstVmo3e? zT=rZLFi6`@%Dt@M66E#NWit)7T;H;;FK-i+)tDbXg_RoCOsR3`dTc;u%y{Pc%oUJ4hE0|iqV!A785tcoTzNM%Dw-Slkb zn#4*5&A|jhUPuE|H|Yvn7kEP>JXP*J0x2#H+V|(e>o<5UreWz#b3k+Yz)kaJs2L!g z=i9VsB$+F{Xr|X+16+qkx5wMtI6qAum1X^{iL^)Rp~L~q0-yg zS{Tp~rpWh6aR^d$KpNa)cq%(s6sYnV8~!u%bT<2^@Yp!4Gb3G(6Q2`lPFyMS0xEbx zzVUY}=dOzxN=E#0XV@~{rL#nBJAbrFdktG#7bT`@ zcUPUYl@NC%oU4RtE5m+3|8aVx%!;l2lZ%IQ8W?{`O1mqucH`VC6>Iey9D8M;;ZH^q zJDMq-b$xOmph477%u8*s{%8wn3}zt1ei&iH&fDdmn93C0q>#$q4Uc9UReF_G)6HoN z2djk%2=oTH)CnF<+znmG}P0iADln-KC zvnTeL3f&SZebb;0(+o1p;2r18wY7hVIvGXMUP+~mavGUgWCE>2I>00X#r-1>YrLS0 zs-1W~7+jl+>X0~a>TJ>=nT>qHs7g)_pu(oTFA5L)&H%uovyLrRAHHbgf!Ebh!?3i% zh6dfXw&g+HMrT?~E!$7FQZffn=Ml=2c*6B7Q!QCVTr6S>k@RRnL}Ta~m$58qsZ=#A zYM$HJO!X~HCUdIG3j5zy&5I;+OJx0e+CJm4OwH6|TJlJKtLENO#Q>ZO*DWezls(yF zvY>Dzw*zS9TDazI%WleKXrFvs%8KY!QbYzNG|ypN$Y`D1y6xjzr9b_nD(GBd+R+W? zfgOKCU3ngBZ1-P)O`RR-^$zL%wC##74dW=Qkhp|1sZY-9x_&UPoMAZkbA&*(j06-G zk;6qGeGp-+XrDv46cn+S#uTrclo6C=&}x!`CO?kho(f2ANy^J;o||!vDYulGsn|9T zdNLv4z#z3_X2xA@1=5dZwX0QeEZHWv>uwpA^Uyh@wNEJ9p8uBl1Z)|Xc`f-Ax9=z; zltR)uM6J?Vj0%Br$k?hOKvSE_rfVmZ#m7w1g%kCalCVIGS#c$-eHupd5=y#1@Cny1 zDlB@+@Z~oLNV%(WBV(p5dNV6`qy>5T_ekO>*emfom>h_l;sEI>-Mo3#fiYLcp>uRyfYqA@rXxUd#f&}IeicC(uG=`twOFU2r4 z?s&_m0i3%=j$j77&v&Jz$e{}tY1XF8e0r3q1I|;dYKrufQ?$=bU5d!!42j;7-q;4G z?WCeY8Xo=2f*RScuytNhJgFf7|9TmifPl{5Wjm!i{Rhs>z^2^q zhGjctI|C$VYX1h6?MgZ5?qupPgwr4v5G`%2|abfY71!nM!&(5Jhxl%X&x(VHn@WNgcx+c<7s ziV7-*CCahMHKsV5`c(-4=M3i}GM{QbCgnYv=QoVP`)KdH{LPC3FVSCR{B?^Z=laQS zEpL;`ITZ}FPeq(PZsZ%W>mC~414A12s+y3eIzSh=lyTqXHFR~dqV2U=c)quZK7x{y zEO7O(M8DCT0SerRz~9oV9^sHR=8}pPDZ=lPJV`ZZ`sVZohxd|Q3!o(~F{YHEI~)^) zTh^rv?YR~d$+QCl8!l;YY?BpxOJyL(=$iBrt9RXB<%w#^t&*}0gDjLL1e!)z#d|2M zAGzwpSwpkqx;N*N@^BV#*lusq4Uc3za^djBslIQfXlaUUMfTsH~M+f2g?OScIg4`{rXgiozIY~td zOu)*LmCRu4qD8Ru%>9ase;_{D=jCxR1HHGpB$zVt$ttbZrKYef@ED5}+KFpRzbfmZ z_r%*QqidrP3v_|o5=Z*2nW)#eXr~%UH79=)wWI`4j5iL21TvMo>ls*)4p*(q)@>Or zIYk49bz?@>*?1hlY-uG2%jW(1;EO~efYY0-$AS0YL{5;v>kF1|h-MlFOmNO~jx!Hq zNj#Vl7-Jp8Fe0P@txTk@Ho&TKY)E?ubrzAgldmrhjYy6#xnxq060$pm|HKq2X>Uan zp=F66&xMjpB8FB+teiRg>b;zstR3aBoxTKLFwcPnRsTz;tOG@|P%#23-yK2mXd>3W z{qYck075IY7qo>e%invX#{@apv>N^e%P+JLru-UQE7SgT z%C>HZYjPSAeDB`QTW2slk zmnQB7Cm|t);y|vdjFJ{W9h-}2MZ(woFcg{=ZnTKq9el}UInTA35?Qip!5p8HZd~5)W=@TPbI9rmeEFKQC+fB1=S)EX%7^2nKFq@W>t6-S z-$QUGE$)u<2?sj^u(!<*?9wOPUIFvM?_cifZ+{mT6?oFyLlv4X{{GaGEsvIQoxd8R zfbI`dtAH*r)>jBb5W-^;^5#+mmi`?nsN+{(XQd>)QeN+h3twyk*;n@|SFMJHoKX;$ zXKDmPNb2{RiCJOmznG=jCR&g3c|fE=%|zaI`TdUau{5AiPoP3(G&hRTSuLG@rzdG=*P^hP`xgIGZ{b(t!`E+zasd5)?!7AH zZ2mSh?w~pHO9V6;n469B1Od+Ci?L-d>foy~GyqZ7(!mxzAo%XuWIGLqp;&e) z#;QC)_I*HU0~9XLW6x)P`_FCq*{j>++}z#?yFJyHJoT z0lLfkDcQ$$&Nqfp=ifjdtY5R=@UQ;gaTWJZ+C9;Aua+%DTL#%!mah^HX0P*9OK(pN5UKL*f7hS8>Dgc( zk-X??@nbSBzkAaGUYAGc+ef0 zIGTZq9PzFIe=)+Y!Fj`kN$gu5ZQ=38`NS>sn!;DAs7C>H>CLT}Q|fy;T+^RNd*x)7 za`7b6gYu-nl;1;g*GQW=DDZ9=_4?RKo20%hkyd8iC^B_Hk!M~vJEJ*K zbrvzYu>({*gTr<`BQ6*vkLy(O67oVD$w>tMOj1)Tn1hAIa!v%YA3_ zGpy99f_oZQA!DzN^`Ve$LBt{~O#gWd%y4E3MyMhI#Ykoj zM$95KPB2rwTv$_I1E}%9-aN`*pkaBmFtAlwXyvrUhS{#%yo*8uZpvIJY(}n>h~>h@ z;EEu^NeYTf?ATZ^(I9~&E**6-j@)DL0rvS$eK03VG`dmu;_ZLfXO9}=s|zwLer?G< z&zr4FYdYix88V;nSas^2uw3ms<34cdB`f4q}UXxy_#rZJdSI zBC$$uSWf0=v7+xtgz_bMosN&=Iipq`!7@(hfwZA*yN#AR(+c&TML zwJy0OKkrB&KP`^9a<(y0=D{;}!y`!DlviO_!cth1QmN}_{hc#?#j<_|h7(S4x*zEz}8!gW@eFSsg&3Co~ ztx+NOqRx1!@G*8e7#C#=*y^TGxIHRxQM|~RLwpOAyc5I7O+f5aC~|IKwL*f?jmONc zKyEQMK5m}gGc#N4_1AipTPOIsHN+GW&7kzXVWK{3q*|$5u6UgmtD%0_Tu8p=VB?=l z7X`B#CuW_fDD*H|sy3o#j*_2O@W39zYr3=D^ z=4_r{#xv+AocU-2Q0mk^<=mysS?ITG5c1c#Ay$K0H+t4d^82>(qL*6h~N{%AX32xoCt{43mvjjGtv$UI`FLZ<6^sd%`?uh*g z)22)GBlo`19UtV|!YR`o&sdRc%tN9(wcD2XfHZH*AA(@|-z8*8WZ6u3ji@$;U|lbI zH%PYczBsJwXFPb$=js?W15L0WNJks1K>|vCo{*83eAFcfxqzMGf>RNg1%0+@3Zo-O z<{>gpV+QAQs5>8rvh5lvdb|W3Zt^x~S;yxKO1B<*r)O&t&s2r-RAPS0D$g+0>vhp$ ztAb2vaAA3zlR3OR~I`K z_GOf#heP$C*YlZu0Ci|0_oy$mGsP2OuzR+@epC0B|P%j_GB7=Ak zk}A!wAKYEI$!&jvnEqtgqHTu~HiJ~u|A0ph(&^SfU8ES#)I85u{m*bbb`cc)X;HJ% zK8Db6RrFbYxey6D~e1YHBl!^b??}N;(|aS^(sx6N>upw|3`k zp)X~1SYzfHz_a5BqH!}EonU!`kR67Q*!R%r-G9I($w=@K~f@UC*;A> zY39V%%;`hEV)LjCF1YF}m&HwFvtPW(?5ftBqAG-JQ~siVI})BdD&}r2DoC%n>!fz- z2!%IA?$Tq+``28!lQuZ5F=q#-dv{1^Bnu@ea_xnbMFpx{$d;jJxADPl_5tfNZb{n- z=M>in@#XMVZZsVr%w1kzl3gF+bL}zrd+iU*6*B{*n2mG zb}ov~hSqXFac94DDGMLY5FLPZ7JgYqw?dh>;y3DN3O&Q7Tw~F1vFNm$b2>lw*%UAP zm*dgnqiPF1GfIN0Tof?@PKfRpPw^4j{Q^Jl+B$6lR)XC{ZJaV!0#e5uojfS*r67I$ zNU~~ZQkZYVIg~*PV z3_*R1%K)#mRYy`O4U#-Td|QxCu!h(|2nfekC;vhWb)m+QilbnL&=6l~@_1_kF?E81 zdXmY*FD%$aU6@9-$=PS6q0ZO#$=|Y9_sfHS(jeE_qG*E*>?Ec{f-KNr&plR0g|$ey z8+Q$U>6Dx~j#!Q(@#s+Oic_*}m%`YR5)>2I$UTHL=OM;a^q~^nh7j#K>NjLnUy%+j zcRUML-+<4)6M-W5r$Vwks)u-8qg}UYw4Uhg-M<6fmGVFPavHOzhSR<-HN_M2y2yBY4Xn_B=D8U)f^C2}}w-i}j#Hp^}XQP*hc}RH)(gV~P%xdqSxE>$J z%-UXj)|%X`ciksWZvULv3+#WdmraKV;I)pqmJhV09syOlln7GTY)Y!IP?-E;@u^fQ@Oz|PEIjuH3KEfXyA8k;eC3Sc{UmnbBr0ag$YI|?w0<_Sw{O6d*~N4A z$Dq#aMYz~lWEVfCAcyB?-4pKP)gwwpm__RY3X(F`A6zA&?n?3db*WFDTN*R{3xfq7 z_TbA7($J`NrX>yYvVjM+F;HydEI^KR0}J2%PuQ8r`Z(M6zg`g?n(@t-{oJ~+H?TXE zeX2VKmUHmLk%5l1a2B_g&*$pDnePTx8c|dGYVC1;rheh$75i}?H189@9~a?s8;nU{ zOG!~#^y0ki0Oww!ZD5~U${1vxGcc%r+PWxt^bX4q_rPg1h56Tgs&ztN>9~jzBnV!S znke(L=Y6g>RbB>=eegN`PD+R<{m49{no?wjJ}gg7S+t%&l{@P?!A|02pp>P37bKJ( zq1p!?PEb4G6*mL%9kl02fvB({FU(JV<7g$j0&hsVo5;A?=Q4MNd#gJ)kBXO)pXk$Zufd*1X?GOyZyU@}>)f=+p$kQ1LuRlo|wwiuS2m-#l`Ui0@Pu?}g?xO9kL0jBo?H%@t|D z)S8SC%uoZGHTN|y#r)O8wchiNgQH99gyP$Wtt8IYXBt8F*JqmI^l3SO!xC~mAtne6 zB)Bl~h*qNXbB_z8J%C*?xiiJb9vUm6YNNlEf~)FDAx$p{UwYSZtf)2BefuXLMk`^w zZ8jwF5BN_jE;h=1Aoms0b&p8Fh1KNcb4hG^XSRfRUJjJ1uNK*QOD#8^E94miMz~M! z*3%xE-|nl%Yh4k%=iRv!4gbL0c@z}{^2x2>%PiWaCcaz+(xuBieYo6BfXr04cpYy@38noKY}0C_H%JK&fyQ2jbzV7?Pgn;Ry(G3 zA&+jz;N8YkDxjlrHHI3j7{sz5@5O2NK>LbcY`&J_1wV~f+(%;=cWrK{fV1%uqgrfO zwJ!O|JY2ahFK~jy6>#D*xF0~|Ziw?~MA21>cc9OF>AF5al}E1^&716f&v{N0H^L=f z?8p@oo48={H}l5}4V!rY&DmqcEs-sXF@fE#HJyKPWa9$?_a}}}=c{E8*4+}n^*~`C zPcg^YdKG-dXLYw70Y~TAFzA5)<9f5tx(v@7YK>$NNKCe`Yo zwk0n};D)7*r;|va+eSl3WNi_`f{YvSAk%Pd!NyK;n% z*yoWIHho4ep3&|J%cfwlK;!oNy7s_2y_||pdT}eOoWsB#!u;<}b7aED0c;Mn>-}DD z5^!l)<0yG73;a>&&VI~@TF6VH{$i+iQBH~APvT6P{$!|=2z&m0_X52*jFJr(dpS;^Zxth8Rj4NboNm1+ ztjrNnmvn=;6O_nctwYq|in_o0XU=Vve~C}n(OzW4YNOIq+X9)fQl#pi0r zUE?^OJA0XnFpLK7<5kMrRp9GIplMg~nFnO2$v7+I2YqZ3J?SET?2Pvsi$As} zB&B4gNGQyj;E@FD!E(5V4w%ul4DW<gvAipU_If^S&-xm3G z)aBgXiNN3cxkyTotKOD0orEwac26<;8aK=4h~vzUE7q2Eoy2oWaj)d5dR@qO@32ne zCUkOBEHFxO=JSf`Lz;vBTCe*UKNF$+%EBc3rK38IF{pHpu@897PbK%GD*q8|^}9*Y z$MvHYj%bWRywwH|t%<4hF-}Hz!XJ)qhKlat9AdmxHc7t;umAWVKaaW%2Hor46?!XN z#@|G(9PJEA+#BDeeT1pr8>f*7#J}FFU?qP4CAsC1_9dbiV>nWMCGcqfkgiVDpD=4v z&?}eJt3bVgtc!*($PqsI1b@pz;Dd=f5dp*_um8$9uBjFCInyf-+5yjj2L6;Z-?X+z zzI5Q2)4K8lJ7sQ{{eZ(R`cs`3HMoM*NcFdgW|EBtHvrSagP+W25DlcYMmQi2E6mUeyEJCgh!u;xBTz_HlE{ z8A7zuZ~dOwkYA6cw^35-OqAyD_QLAyo)jJBSCA}HV4Cm(3%K(;+oI%`pu@mjAUxlV z(cI18z5`#L0)3`M(Kp)i4$l2vG&Bx)3CBnM?rRn1ijZGeThFH-i?7+VIq?f%2rEUR z*l0^5x36A+KNHx5LV6NJ*a`_BDQL2JYhC1;E767eoJY*gMc6pAYk&Tn z&YZ){RTwAk887(J6imzih*to`sQ6eAua}e(E|mha>cbV1l`^Oltp`tz{6i(ieW`(e zK*KvZRG+(Ulp7H$eyBoP=@r!hMR9ZI@)LxwfZTx#de5~8=|qAO((6hb3R4X5 zCF(MFr_2`blJUGcKZ)N%#8hRPb5{j@twq#Kw^o?$WlC?h)L)0Rr9TM&@ z(YSUz{&WDVF&{u|TpTxdYK=hk-V?>v8p=8UegGAGV2OF~VxP`&*{`hmx0D`T@pIXm zL@+0bUdewEyQJBBeu-bZFGD>%J|4Mrf?e@!TgiVDyX2u+H$D-&bh1^~jtJ0Q1XZ8m z1RPBSej31SikI_L$^c!wuNjUBJMbF3zV;9}7-XIIQp25LhB6?A+U9rmV%R5lAN~rA zq_6a`=0aid?J=+}JdOQXtb(7Z z(o1}ZZC+p~Sv1&jHv^Wf)9?W$M#){6_y z1)ib5mAy{YpK!N|e8r#3Pb@1u1DeY)%0xc@;;VU`IXuyLYIW^z@0|2`yk;Hh+!hE{ z5C}ivQWrt)fz=78hUWSZT9H>3hvNog>-%(<$FQDZXSn29)AlQ`tja025C0AXJ|}2c z8J#WR*NnW~IS%TYmK%W+3t@%!BX|gj0nVUQL}Eqd-w?azv={5C&bj^EI6Xz4kqh2Y z0%ccrAbXRkefCJYBJP1xa$T|G>)U9)`5pbFvHORp^)!G)o4q3jB4p}wozFX@{+&pk zSP9CtKYy(eH8vvTwgoK~=L2|gnn*rMCxUTV_>=e3Hs>ZpHT1y;^yHnKc9Eb=uuCpz zsRLD+Kr!i!B}VyX0rQC{WJ%xh?_0RMqF=$1PlYC6uE(F)4uV3i;UaV595d28QM6}bt zhi{I(%!a;dGSBIg6iXr>CJ!r0A11Djb15YtiK=sGCB+5tgeK!JI2% z|5zAjRJ%fNR&=*;{)TnR@MPq{C7!X}JhGPt-N!8OqWK==JgmuG?FLL(_$GpZ($hsf z6$7O)|8!QzF-F>Pw)@h-(GnqXU^q6IvVO{Z;}{@0mPpIkxiEBWGE}xVl>(%~U?%@* z7KpYQPHBs3*a&U5lN^L0PnsIxlQEbs4o<48V7ILdY0ab3Ez;rJNuvDW?KA_*gK_o8 z6^-V6Kl1x^BOFsfU#KI@Fy%T2OgP5Sd7@$a7}YdaE83VuU%nG!mvGz&V6;vr|e8gtj37qOVqxhyelIhp1~`l+$tx?kXN(_$}Ck+mNYR4x$@mVm~=s!Yu9~lmsLw_EFN{k#R1Lyuc>`LJ_XNBZ*x1dKzOd;hG5D5)ma-rZoK>d&@I&&AnS#Hj54o^$d_ zeJiE;f2ZUFKGo`URhgEH@Qg?WG91jkT0)(e`JDiLH0v}FMhZKKuOBoJk;*@x->j)K zr92dfIc{HywyH^V(bsT1XI_CtDpRaDri4n811z3lbct~^Bfu6!j*WZ{_JA|p8dsqN zGl9xfHqR-#tg$auJ|hOpxx)cu%Q{nX28+eA#sQ|wh_;yHCjoCKRmP9)crHb}>K2yl5tuad?6ewJk;Z65A;{6Ue>L!#pQJ4sI+$5&rM*5*b`~Y1ox~17{?E zW2CdSwgo2tnen}3#l2uxCae8kf;j|-w~Sa_hQVH;j51EvTHR=R+Kw#8+4<%hyP^H? zHMLL}xXS$sZYDF5rHk|W2+c631J#bZRXWygiqcI^O4iX*w~V9iW}j~;INU{fh2Lmd z^Be>}NdqMZIw?Z7qNTF{c<9Okkr+>E4(!r-fDlTwc)C$#zQ?eYmI2xQIuK zpbP0KaY2%=L1jR`o(u=pNqc$WpXxs&hAX6M%2B-A-AB3Fk8O1a?y$U~@QXxx&F1cn`R zE2pk%=aG%qNLlTKW;-Vu?wJt!*+PKen4L^!St@LIe)_C5%IB~4OXWo$WspG~svWRA zVrVE0bf80A&<6J)5yL8oU{+>1545oDKK_tnuXG^kpe3$4bAeibTeLQ-Oj1&;ik_}R zd-A}h!$h%(lt7SAprl>3yW=i778lrRk~By^4sg;|2AF%9Q6#ThvcDV~tAtWqq)?nq zJ^R19S(BT)v%z<2Vh%_o;*_5v9=r%m{lshp9nw|n4J$$tu9#W+>p`+6{&XZ69^&57 zTp7un{~?G<>Ecq&HJ|)v=CQwnEI@up0AA9YXu+5ALp(eUsj6s>)?J%Ia(B+*a=KT&{JjB1u6p zqyL^b^qgubJGQ4?P(Lho=G(5Z3qWCpGMl0qaQAQ8qgHXiD*574!sqohb+&6ldyiD8 z;BFXWz6b<{do1(c8N*j0uU+s04oXmQ_n2VK>r)KLsPm6DbOID-v3dd>i}EYInrTSe ze&6L1S#jgzxCe@Xf?~4%8O)C*1Dyac)kaF;DZud#IDs-Kvet&Wfa0W@gtHa}q___; zwoCOU{aFr{rlw$S6IL-RyVzQa+iP~@WX(B zm|WlW&vqa8Rz|;@+8Tn@6x~Q!MH*`1uTn@yC`|BYbm{|W;#2gHCyTgMm|2{^R~t5gRhTaTNk`2BbD#;n zUqkpZ&&RYl=9J>mf}+qu`_&{bCVT18T(;!FcCc|BBl=`vy@UOc-4mmUi4M(<1W8;} zVfyd3P-Y=Gp4z;XXu8TgpKLxn3LG{+q>R0Y@~^~IQmcbjcsZrhSrsj8j__TeHM_rT z!pX2`2k7xdeMF5a_YI8|VPYyiJM^9Jx0@XWc)OIv!Znup(9#|$f^HxrR`-{%YT9 z9M+`EL4HVM9`7+&oh~V;cEcQ(+em=@MQ3`rk+2s}`)??|c+_aZHRL*6IOKs808fn7 z`{xRaB&ryFS}M{;ZmI1q*kmRy@oY^=MY}{c$B@kq93O*Z=BSJ{n_w__%fCQf97g>s zW$;h)mDF5PjjE#8tJ}boU_OTAOl`6ux*LmXJeV^>-zO{_Z!ViG2O`yb zNo@+B!=-88t$VsB?9+!mZy9>=%tkli+#RyCM{QHjmyf+3yd}qd*Ztvr*Ax8mX}sEL zSDhB!q_{R#4v7`COuWhn^DA@p0R%d6j(B+5%m0V-6?JD_ ze*D8BK>R@p|2Xo1>>SM*Z0$TPZEOq~tPEWZos1nV?VTB%?d)uv82*bz@IM#M|9l7< z|HF;9^i5#qk&u!yW^1Eb^h5iCd3D%nd(Qs+x@j}V ze;xT80dAaAQw!fuP;32_Q!WhV7ItfimeXgBhO3M;XsG#-InMhWY+vIYH>#LusEk=` z(yGw+NzEcp!%59Ef{LrbgrJ`|mLmL84+9#8#+yqVYTW;t8;C;0i`qXx-$;f!&Kh%vQZkj5PC>3ALNJZM5-~=yOwR{C`+`%cjZ# zAXyNa#@!tnXx!bQad&rjcZbFGqtRB(QkI&A)gteo*XW~O(+K6(}B(0Sx{ zNr2w?4esh&RrvPq)3?20DL>33d0uwX?ljeBz?X6zk{^0l5A>rR%%|4iAqPhP_Td{p z(R+>emz?mI-XQ-Cp3+ZjaR4XLUGNBD{$EJ}MP(R;q{<2ym5LRq^ze>S(Y#v0rXcaH zS{dF3VC{Wz67K1iWG;cAOi9u>x98Mqo*9g&{>w>NQQ0Oe0qHZB8XrIw3Pt+R{{-Vx_oD868XVnr>!;G@Hf@w;Q)V-+lv>_-#`+*9Qv#iwIBMs62&Z@nbv7qAak-483A9D_+RSca<)iD14DP%y<)kJYxB{CDE>8h+*-|kB$HFw&wc!q3Pi|7dx zp!_znyQcAY4mxC>I6y5CEkb5$FD<$jlW6vcF-UlY1gxN01&e&Zbi`f3Hib6s0NBig zJ$f(QoE_A`SbBUgVfB~@Y_XWBebR7U5=TuQ=-OX+;;tHE6`iuUwAW}4a-GilcdLK{ zsTlNHpK#3;%QO_MfDizt{amw98=%alGd7Z)nQa2fYJh&Bd|Drr18EvjI!h67j#fTT z5q{2M+{*!ljzvZ5O^B9WG0RgH09)&F> zXN6|OrupaCvN0CJq7lm@D*5kp#fvo^QU(w{=%ry1eboE1OsX#Sbl6}?g;-1jK!`m2peu~oU++2T4<@sMq z5n+tNPz<~l(I`UW4fr#UKHJ=B`$BOF?n&*nwVV|6aYk$m7c+GegC_=a&MKrs3k3q4 ziIZrMXvCsDljL91^X5gF6I9_=jp^ynN7Fyt1owM79`fy@N-dHNszhlQB-P#isptSX zbRE*EP1GbWGHVoYtLDvlZDvkH8h5P`vqaeEz;Sd!m(87#o2(kc*r=WBL{nxWSlbi1 zSk?ryaBR@aBPg|FaM9L^XI=ZQq)N2{X_XOmR2`e%8(YvOq%~oL@+yB-4i0Lh{S_p^xkPevvuu=7%t0eRRxOpn(IKkS zk?42<&GL}4X#t@vSFiPy8S<8$L%+hp!^2sbZ8FohZ}rOkaz=t{RsH$%9mW|R9v<%U z^jz{cSF;=PUIWN4gF=|*Q#?F}iOADb2)&|q1)v0;amK2^Iu5&a2>sTWdoX6}T!ofi zSe(?qjn2O7I2$K*Et!mnT$6^i_UDNsaSq@_Thcm>mGg@8hGZsT!#~7GTu!^B0y?i> zTvZpXNlt_i-$q@7E-gbi7B!J#vj2EWUg?9=AY9BMBYLF5Cc@pcdYbPiyD;cZ8pz=T?Kz&bE(UsZ!rKDm5{x7RVh6 z6EH^>Hm9*8AApjBIeg*XVn}8+wfnC=5k6QWWFuvO&`qhTy*^ElE#)cxVlmt==^zbH zH-xLYME8nv-QY;3CGg+yrZqU0_a^7{2JlI2PKi3&YPtdDI7-iTNG(J*zn zV}>pp`!6|*wk`p_PNjbVFDO!J>5kC}mhIN-My_Gt4Q?86E3?cXxGcH~Gt4jZl7qcl z6)#J+nv=X`hPc{xN`PNg4Go4#&}aMFi0Z3rn93=V*HJ7*(JuA7H@M5~*- zdTXsoZlW8!Y2}$+d?Yz$sF4DcfkmsMlC5pT57W|CgN^}3?;Wc-s{?yLk9JeC#6ryY4I~KtCX2mxy`bt!{b2mJSjpwrS)%kECx0iB z+>9PU2fd)8)Q3_L6<8uKUTGq)9XZ(zdN5Ju7l+#CP=CI6F3rz-ha$99qq%Q{;t;e5 z3ScU&%ZFU52N6{EnwX0a(h2i(G4yr>zPoWkat#n6?BgU`8n#$*Jb!TX`orzv;Tc;- z{|vCYmHc%575&xg(y2vSB}2IZ%c*`9k|#?NZ=Ei@IR%`4D`>y#Naa6Wo8gh|gkcxd zG{5qa(yTV5?eF+LswE?5e1a03PbG&r_aZ%F6=BI##4|DT-z+ul^QhD(s=x$;&yJ4= z-mlzP-Ey%B+%fkuA94>IqZ^$2S%qgahrP^))^&mVWZpV~4c9W9M$k$A{+JyM`NlJG54E#@%t)!c{GW&K7X)r z0z^~QeS|A?U#ajws+lKCWVH*N{FQChiDpidKQ5qp&0 zt!Gs_;SJ6kuFD<{gksX{k4&Km^r8fIMD_Vl7MKJXSTf1in5A|{`Fm0uow|z7Z$=h* z-9X?C%eW)i4J_Y~b>G|d**P$04{F`I>3Sj9k)vPdinwFa4tH3!ep_WYSsJba7o z`6H)*aEIWP^s30rA?PzaKjMpAVY++5?AmrOm0$?`V%(+FfWLnWXL46?r|Qyhi@o-` z$(a!oK?8QYieeK#?;za~y+m(!5^o!irl^Et2=}GDc{UL5G|C&6zKGcD_|m&X^u)C@ za5;cs^~>!pJ>dKlWNXlhs546R*0wXm?x3m>_j>TH6>dX@*PUN!kz&i2C4Pp#TCMuwTIm=`&QwU4;X zxFuqU^$*AA`PNJWZZsJ*Mm(cLI59DI3PUkuZgP7qC+E5ffkzpG<)2$?cs9<*tOWM) zsO~0C&K56o=%`p$(R9>$?T$Z4CT9W0RtKBv>b9!cT!;9*z_5Ay( zT9wtGT};_Ik+59!E}a|Ai-D;$%X%U6$^iKR&f{-qUix%-v`28yfRvz?Uq>(WYnei$A>M1`FYqwKayw z8*SU3mbVwl6HD%PY@X+hNb3_pX?t+`RtZx-<>r=c$J;w-8-oAZyz&&G1&iMag+tm0 zjnHTs?3t18s+$PLsy%_S>=yM3{Qaj^0ux_IMB`Hp@a-M-zc$ckjTsMD-*S^KBnSxa z|FCQNZl>hztSyW@luV3VzCDsX{;%%Tq+%mCFOTLs29uy^@C#KyB$3Dqw7o18DxV{D z7LHUl%$Meni|*93?h@*m{M~TjnVQ8w@_pyqMHhRTHV_HtXNm18XUkLeeP(t_$;a*e zx*G`RhFvfq5)G&rDb85F`x_3P(zs~EqBYzKr`m`n99JPy%t6V&+jcE1Wy3UD!vKaW zqT;CCVx?G#O|pAD>#i^W!@|gh;)EWi#aem5%67e&h?aN!(5gEQGkTiMyWS?LIh%9| z%6f<4UNLuqG(*DKFW4)rGT;_C;X`CSeWRLcgNtb4C9txwM#ETf=IEy+DD4pPHV?D) z8+QPz#7DV&c!aj8^v`6336+Rf9QTDnQ~kh3$(^*Srh0LgdAs)3GP{ZfEO>4=k3HVe zk{}()PD*`@esY{*NS8q--UJDuBi-q}Nzozd*%@++?Xi09(pPOoZYstd#Uq=waWP z+ag5T&E8ciphprlRv5Jh8`UrIcB=IXbnTihwRx85Z=VMSp#OIXwBQxuk%x!>o?IH+A=g_68zOZASo{a2 zVHm|{@qvm>LO&Tt4;?O1%sPOWF$5l=NXk}<6eqts{;`uYAE^Kk>f?} zWu-}xArAsr5eYV%ZfI-SIp;IN5yQ3q&+0%_d%Vm6O2`6reRZyAt>pdYK-gAcd>(yh zi++Toc!N$qChRK&XB?op{?8Z@xg6%svWKj{Tf~H`T5{lz%*e}MU5JY4+@uj7h$rlZ zsk!GAa;Qpw#$0S}LFSZugq1{2MWtrB!-+MriWivxv1B@T#s7LcPkFzWY`nxh-o*WW zdqa`NYt%z@@4`utYoyp?92=A*oUI;e{wC`<_7ym)YLSxe5WggO`}S^pA|Pl1?pGsC zAJWChtzDUP%8lT^w=IWBFNd)Vp;k~Qf>hM(X$I(uVIP~T{I|EZrfDeL?PYQZk)XsH(h3})XbJpB=T*NG-iikRDU&RHP3N35SZWS^$|8;1MK7oX#!$(f zc*F2n;RLyW+F~=b9fTQE+(Kw(gFwho>k9P)D6)H-@(6@^(#z3tZKgOqda~9l^}v&+ z5XAm7=YHg|vF&>KYX@!hBr5ZrN@3%AnHMnI|Lxl^og}i@0Bo15xNauP6bZnZqI%g= zZ|xj=%Hhb1-7>Wr#PBa3ufO8 z91+q&nrRWlt@lE+R4dZc9lb1^*OUK|b5T!;(!|9Le2a$v{KBnc4WfLdE-9OZ$TMM* zv;y&n*E*1Jh?^eDcE3Oi-JS8{IuWX4QCVaCijVRs56LouaW z6`q^0kTE|ZKOro5b*RT#1mkx|s6>u3bAU~dzvK@-#qxn1Jy~yE{j~wn#|G6X5DRaf z!x%dd;uPBRDTo(?jM|ECGWm<}g}X61d`korl|@my5Q*0hwjnffQ!GeUqtpqXO{jjptqJ4gNB6&hT>|6CpAuKnYJ+` zSMUJ>R=)L@U;srmLPvn69z{2%oEVQMcI0oOsBQ!>4!r-Z!< znIFtE$k!5lhhy<#b&I}(wWa1x5KNU#Yaat+>}i=_Vj;rGvdJd7L!S||$cVIki+NZT zy+g?0GZ~vVxM5YXzH);~1mMXB&0jW+Lg`oX!wMrg;lHV=8yxt=SI|`Df)#P|hQMse zUuS^4jXWIc4?B66yC|wB#S`>NaF5=9;l}-3AsmdOlwMPOunwVp@w$ zWDL#YYTQeXq-UV%R%C)FL9q>qOC~Z<#)=-r8V(AgCzT#E?@bKiX2JpQWid707_3CP z4%?;1*4xL$-ZrF*d=o4H#GyBk`Aezmn>)5vRSdDT;BPWr7eZjKKnV%WG2yGRZdxo- z+|B6O0XSxb(i(RySSK7txq z%!0N(b`i_mQ@-BRl-30Fv8HsJ+g+k>E^LAV?q@e~t;cCI;59u|*x$U0u`T15c+AYD z&&dd>j~X_z6&oNdh%KZ@$Wq9{iQ}fmBWP!PRa3RcS{7{b=qTUqjc0|dCnff7E-}e5E9S_^~pWa++N?R(< zE+mY`821~hJ`L@W*~}^}=1M59{~9{#`RhO(60JVQBh)ATUNF)~fyq@u zWD&&`#~!3q%27u9O88~7VGlDWGb;--xqlnc9(IkO!NCz7!m5FO&rG4X(cUJ-?U67X$c z)RF?*c}*2qu{ZGs&pMp_Gal|Fd9Y~cn1vsIDR46diH=({HmvP7GfZ661FiUM0^Cy zXt9Kag^u(8LenNE5*PHDd^NYvV#9m-QSdC*G~WRuZ!tmqBTCgt*e&jXE7*3lU`Ala zZ1fY=`z(%AjmW85@QB%4)+%7aq#onpoNb0dYM1A3p00<$GgoqTB;@SLx;i#mv+#N` z##fdJ*F4iFs@OTR-o7zN{CgI*C$lWY!G~I+o#h^wkWJ+{mJtLbWl8Y%R6_7@RElXS z3QDGxWQ3up4Pa0meHu>eCs#(33tM2mbBh|`DLFoYjodwKb~g52GuRkn)h6!;-MC?} z+XG7{d03PbS%ke6e)RqC#=9Es1=fDwpLNggeoOFwU0bE?42(_wPYh6z^7Q{pUq4N? z+M6pyY8wOi|A_e8n1~Dp##;7J&iD^hP|)}N3n0HJ_A@Lj zdXx1Z7`W|vJg(oiI@y`|{e1X;)J6_t7c%7dhXu1}M2yv=tFkyu55z-<5G_J!YQMrY zEV_B;aL3uN=S6bM(!v?;4l&*2SjDK^=_GVVj>E}ev`-N{WlRBv3rcZr08nbv`|2Bp z;3JxgT{+ow~fk++#xeW3XY&tiuc%iMAB0 zag0;>+nzk}BzxN0ySksvSO!Ubw&vDxZc3UUVmJfqx~5{Q$BU=;UB##VZP(STnh;BP z&G~IhQM1pW=vV_Ev4%o^r||1sOl>*zIRTqsz}{ihP|`eS5Oi(@%TN0Ct5TFRgWuGf z8Nwkk=0?;<_Va?pQW@*|Yya`f7^mW`aRTyE5ikwf;aHq-W;S@LjVy1V-_!nUtoS$SEv~vwg*=CsIav5PFVk3-g zP^)7lI-bEyZ%Guldl3v)is;4hW&-?ad>YouA{lu^5T?x`;?DnQ_nZ9D;>3~Gk{tWR z9rI&SvQ)B+;;T}JhE!7QpV@DOxc3D$@zaqg)QMF-Ck!=)qUDCvA(imf;{9q=S1@MY zV4O*SVSR)iqhoGMc`7r`<^Ytgf=sp#G+XcZlvAvT2fRkbq=sS_Yr-Ghy*sYa7FGJMLB;Ya4#w3ubA@0i2ejX6NnMAIrD&*I&ZX=emGNcfp~A z{@k3A=dysRR*HQ}a0edReQa>(cWL!|C+z7lcUeK7oFs<_hvQh=80@x80~1FSVn`%+_BXgnl_+fP9V!-A;_dfbDT?jv`Jc<@l~U3`e>jwpK%(1O@Sfe%n}ee8+mqM6TnK(R!TlA zReVN3V#Lvf^5garh>~s|;xW?9!kf~u$l!t*eK))(mA1=W>qYq*%N<7Rf~mo9up(;O zs8w1yH$*x>)h7jY$U-fp)Li)|A?SuuGe==q`X;!`%=$h$!R)tnbV}WX*4T;c z-N>#l(I2r3cI$3&buCG_ll_hXvZG{3<@-dFm{W^6JM86$O5g&@)j#=GtE>)$0~<0a zm#r3(z10Jg#GvYDLDp^wPX2xg!00S1=!JwctR9n*rsT8m61;|o7OHRAnB~NtVqx3G zb%XSGh~>5CNi8)*7&<@Uyh+w7O_L68c z1VW1{g90lmplu=|@IjZ&w=Da{n(}|*v1ZN(2d^>_sN1lfkTk2os>;(*HQ?zPSof#b zsPz|z7fZy7oVvsq%QuO66yl6gs254l&n0vs^6-KcZ(h z(mHj2s#MU4wt2Hn)vrXIopuE$tasiBrj20GCE-$y{G-__X(dHlY$~g&sF3O(iFXqS zrnUfAX}0W?g5y3`xk957`{GYhlNUg*Q4H^hAvI^*L-0rHBl7+opyiMe6g4g+IunRk z-%FzsKYkEVygng{FhnV2ly-rEm2mM>)$Qa|3MvTG_?1D~`sGkn}x-6H7e5I#YKJ7D>y9m|yD8GUQVgs%EH zQU1e9SN&cwaug0@3UHXA98pVBl z=nl2uK2sBLM{wKhIEV0u%Bc-OzuJmI-g5Uy;f9xy#R?s@JR%GX8*Q@A;uW*sHj`== zsyBl&!V)j^USMoV=MH7v)#fh5$0tT8maAdlz03*W6^r*t2!4gWxlw1OgO;RXWhX59 ztJPltC9$^Iq4=FvjRPNBv~2bP%uOLW5$EQBs%NE#qq%QM`#wT`%JVZ&)S+Xxhf(C%jcOwFLVQk~+Rn{SX&Vb9ojtS3%0e6$3w2Vz zBWmARh`}%&d~1C#Nh_tm3;NnoT}CMv!iHZTl}i2KX0cf!r3)BwG6fTUvB~YGE6azz zCBDKJwi+vjrouoQvIsv=%yJKUjpN~yjle-o5NhwL)m(F8O=3y0J1fOwj=l8 z%!|^7B1W~FiO~UUA&&Tjub9B^8H1k zbif-3d07bcnvp{U4|64iXeBdrHJB>FWDuu{Al!F@G^uzVA6kt`6X8S-RE-0@^o4-a z7PJ~hGYn*gigb3CHJUe;kerZTtuXID%x7qxDzh#c15>UASU6${C0ZMvTn`|RNn#Bt z=)Fj!)Bn!kHbu^@pCk!$wOsEnOcPl*mRReQxM~T1V4Xg-8e)uWwV03Wu+Q8eDn5ty zURZo$^xjxz{}W!@-JJCbfif|DE}7IRH0!2A${6D!D^UeIS)7*k1T6^5U%&W}=dv9m z!@NSpxm%n7L#SCMx?_cU1{NRO9tG@M<2L zFL)0o#VeshEX}i>VW@@mE#AA8h&k-T_ zk}clWrw=MUbFWeaUN_#L=?y|MlPWJMc;nT9$7S<>Q+T{SQ}sWehBAe@nxpV`O+q1#`XvGmD z%#PaU*RFiMB+f@3GRD^%*DP$@B0RfnmN0W64&2N_5J=S;c)vVHW8*w_RHY6IDR z9--;}Id8Ix^K)iRx(a57sDIyEu8;uKN-Wo4H+iziJo*l%B(3Em$2DzNooN~i*zvs- zD4`Z#DZQzwYBRMa`-(s!oC|A*bhw%W=7*X?wkR8+Cis%VGk-JAA_s_7c3vxL^`phV zorJ}+tOlH_3=+PInx4VMky^iNh8>fE$5e+uo|2;iCWD)-aQ=nwY6#j|iw43+1h`qi zW@~L4$g>RZ>JG7a=gfZ=Wu7N3)W21mtOKa>m+uw8mYaMQw|APWrf`y()!qKQIJ={V z>^hbwkq#CMAPmK2x#CSHBjh7aRwj%CVVQD-8Cb?xZ+;uhcs(f!-#3gi zN~Zd4&e{bwL7Kk_o*uas11ckI$i%giHw_1mU`1;MESBWDQPi8$8@wIF9n%&}h49;d zlCINYu>tM5TdqAzrTO;w>NM>uI>o`$&BR-5CSq%aY1jXul&tS5ARNUlAL=5#I8(zq z>{K_LR=A)nh$2a9-2K~cqG?$or;(z zhxmfya(yrpy9vILn@b0^UlWBtArC{giqDO38#QHe+DH}2lcIRlbkc%9#a zp9%8aW_v=W4C0?=9$^a!k#S$4<4)*MfQ_NczqW@$SI#y>6s=vJC>2zNrY}ZxC`f>; zzb!dj@7W4*qQCll&5t+$wmAGj0WnZt!$Ie$rO#+;x7fwEoLx_P`p9~UkY6wr&s+ns zg%`!MLd}+;WZS|C!=$f0L^C|WCAj8G;$pd{=%+51#ID7FEpFl{QxqRzHzhf}{Jn(VRO^S>y2(WSHpN_>goFjt)mFt2%YOFc{UfOrc0&UW~AbAp{>DL%?dJ^AX=X3@e&fAkCnPnsNbw@OE(=pjGt1bN&z_)dWyFVlJlWiDI!FR}Fjxu)V*AFawiatcNd=lK z4bZL`Bd_usun}xfRnf1RFRo{y5}Sm5O(hDaQ({vRt+w_Y<1h!+8fXCS#BH0K;zWEe ziODG6Yi|Y|vpR+i)XN@eROS_-2G=AB4*G3Od+DQ5u|+0vGV?#2wf}!g zh@y$9iKB_F(f=(Y-71CYLdp?Bz+wx;rlhc=@e;+tDqN=l9&WP7~dyrFi8lBp;Rnj?vi ztl6*kk|WmP1`*`e;r63=Ka=0W&qojyNnDhTu-1~|#1$dT%%V&y6vrE|5dgM&F*eoQPo+`H#fsXoV$_if$!hp!K{fk5dp4@etc>%#XngE)KpMQV;lm0e&LVG7J zE`D;7CrlXM3F`m)vmy`_Ym5Ra5J>?~Wd0jkd_}-PTsPkT|BV@|EmJ{uXt8X93D<0C zZTc~bBn-;Fq1B>UrBx-R)1hI*|FLk*dCkq776hH!^QHH`X*0$9wAH|KyzzFldQG?{ zB)or+AdS;+X5rvU_LVt3yVPcjGkVrC%* zXOecJeN}w?48#6-plALhNn7nW&+Oe4|EbuqZ0=x#@fBV(zvp>rJ2lWq%k>07zI`$@ zrseXI;e0eHX&;f`S9QK|cC`NNin*QF=yvv=Ow%24y|hO_zFkqValE(PN}1z#zW3I& zb#!#u2^_8BdIB|h$&Fao?o@iaT-!d}3u)ZC+zV;)6^`Kb4DX`bD#;Slc~8AMalquy zd-IqZecNQwF}Y8S$XUuW(|)gv$Z@*8Z*RfWe&^15_QLEr*-LRgF~RKFJ5bwvhxC>4 z_?n%pxyPmZOo-TC=xb?oUmv}uXmQ(oH}jny^>es;ll|-+CFFV`A^%#GX=*O%V$@QfP_rovpuEels!Ezt|;u0g7}`@Gt#SZA}$!lW+ad3r@$%v6LK+5 z#Q^Fs2||nQjW`A|;T{%a9*DDd(G+Ac4UIA<(a4!aEfVWR{3xPa@X#$mYb#WTjF~gc zlp5+V3Baow6fTi=9AmV#R0%s6H>QnVv>=ra#!DepI&i0z{hMxFF6CR?lhkgJCi&(3 zNfTk4VA1Z2{gZ0GiDKChpe37_psfgMF*Zt-ktSQF44-wJNQKUKW@#PYLiIvZT$#RB z`(0v=Dr^|iBE$7(;8MW7<3h0=#;l92-<~*+V3@5TtOODi7`gE@JEF_v3j5%GjtTaa zwy|*m)o|g18M)e+(5mTe;i{e>e{}C9buV^@4(4&-z zA5WP~Q{!#PFZb4X$>eM}(x<%OM0o@+xcBilWrkNz9$MfR;4R3n_ttoRwvqnU7|&-Vm(jI zG`Np6?Wta@+OQOgiptv=6R+!%yv6f^z`{muXy&|#sje`$4%iwZOujNwqM`l~Qz>2# zF3W?5p~A8AodBe=p0UpkO@FcM z`|V+Bb0d~IL~ymHKAk5BC_13!l<#c^Wn5;0m-wW0y|`;?GF4h2tWSOJe^hUggCXEh zScznT)F(!8s?u2BRIF81qqwM{Z{jd{&amF*2}1lGR!3YN(wa5(*Ct@Gu=7fN;Qe2# zt?ZTjJ^jqhQ4w|*jvvjh*jbO`LTg#%PeXDIi`AoAi6kO#F-g0T z$$BW2MpgG#WHy!%mfe;CCAU8#uTg)RNg2Z4s8m^0Vz@KAnD=8bIHxp8JcTtd6B&m6 zHGkA}SK9_aV&0!BB*XBR1%zG_5A$X>M5C-M2ac^l2-NSgz13uqg`G0D%-x}XO9EEo zFTxN>N3=>vKC|FtU;DvgLKxK#(1tBcimJs1Hz{MG{Oyt+QdD?x;sBEBa47*+tLi3} zlmua>79u=N)OnSjDckmH%Bymp4gv$o?jQOw93y~qAWk6}!JMZOF1^u}`5U=ksk<(N z;rK!&HR2NB@Al*9vDAIY!~pUiUB-$8jKHIGkR3>81Mon`%}aCHKz=OA>{AJo%Z=RG zTwILB*bmDFvG`q{sSulj_{ak*)%hBPUaR(` z0@^3U?~!8Gni;q}+vwAZ20=?eHZPW7K_4M)4l9_UdE~-51Q!DPHeoc|+Ygmqd!%6- zV0g5E9!YanQjml+EMnDy(EcCGt`adzAsO|2x4D4iZz2BhE5`&;x!&Y&Q+cI%D_JC< zU=-$rcVEHPb0nHe)^DKRCwA%OTxOEQc$7ulJ*jPqsRdnn_;ch>`p8YLf46^Z%@jd4 zs8Trh;#$s*GGw%JA;)uG)Eo<9JVtVjC|7YE>1qVr+wk)d`bWud&>}tkAc6AVIk>Th z!}EL`(4smzOZ>K05M~hA zSlxECJO_%gVpHP(@UoO-lws@hRdBAQd6_*-gbs+uuaGNIyfwz6P%!W0@eW!RrfL2I z(a8#!ue|AG$bV1m1cNtn7;7+F1_X>y=Q|0pVcWY(+Wbmp>9C=%GhkCv$P?GVa)jwJ z8Nu@$r(^|8EKc#DJEAY_x1=mM)MXN!KBeI;u<0=W1_~B zD3b_4WzwOnhS`WGC#u6gB#&Yuv(Z(+yY}G4jiyJjyBW4)baZw_L7Fae@&lG*w)I~# zFXYsB&+vPb0wPTFItjM^=1yu5FwkopJq{?x%p*a3j2ep(k%uzdxo$2|xYtxZVZm(& z+S+)GH@eKLCSb-mZpZh-VRzMdFPVc@wRR!TLvFx5=QT&TM8Vl*wRK{1cMj+}l-K*a zro$mH)yG)>#urI$53gjwqjO44cNr@JXp^PjItIV@Q>x)OCc)&nK??aH^&Uaa$ow47 z#~RN^NEX2u$GY`@X(v(}r-yG7UG!dv>EghBV1MmUs%AYlx!hh%EMa{EQ>DRCJ%U9*1mpu*IpAZ!MsC#abeJ|`&rKRI zwBXu6ar_%>?8l-2)=3#~Z5l4l5!wjO3lnvvKubT`mLWIqKjCAE89##<&o*I7!$uer_veGTr-eUBUZBR-arz;?zW?8!dO^;^G!3ms~d58Q(mX)%JO z%YoQ8lMJGDlMtdRo+(O1th?Ms?0TiO-Cqwy0y*=Tva2Q|LiM<(^8yJzJ6+kWJ?&_& z`&QL&2zqHlfBSCb8C%BE4b|O`(J4$fQuv_OR^Z8 z2gKJBqL|Tr%|8@E2F=|# z%ZKnK@1wEo;0CWY9>cM2htmvBNw!8#zcml+tYK1dY{LzQlb;Ugp<3>``?^|N`YJf| z?Gpey6eLJKAh%;7j2{btbTF6Ha%k~5pDJbJ#+_S|VhR4s#TKtsf@e4&%Px5*JkFik zOX_KAjyvug=A8(u(|ASlDK-5s(|?&7CWox7OImg^PqT$2=uIU2c($*VXKjaz_vQAG z6ghgDZI$`$_4)1I8ZxVy;j23v9YTxqwUqOaj~#IkWL%t-j$L&T+$B)w#0sckBCZKp zDzBDmlkjg3Xb3*LqDg9b5~j9Wd$y=Ex~@ZM@A-Vq>p@-jLhZ8Gt1o>x$D(`K!Nw#y zvPeDkG)pB_T*9+7GNK=$rRR@2Yk9oI??RiAdpU@eCBvF}Af}3rrJO|=H$~kf#+r7~ zO?kyGOM8&=g{|GH>P+~aH>^aVxoyP@zBAg6p}4Uw!4kJ89-(hK7q^vWS#3X%B6#wk zp})9%DtR)GAhd>{kqWGEgQ0pWk*-1#!2>tj}tcF#2YEQs? zagj0#>D!||A62uJEUMWI_rq7krq!u*rA`vT&Hwz!WplMCWDx&Ik!4%z-Xz(=P2pUipDVafup%mHd*aKCf z?J|8%PnY)Dx*;$u$co?CZ=WH@YxnY0V{uR+T$#i$qY^efa~Sh(4Pl;?)Ge?Yimj}O z9{yJcnE~px$e!T7r{5;jAN;yh;v7l?=cYe>0*s$?z}H_tG$3tqdOZCV-Nm8Ros{w# zbZ^6*jqiuS|FG=8pyxP8>m<@eJc9>n-^PMn-njMrCPI@R9{SN(az54YL*0(1G6h8B zfa|=W&esm^4Ywn-SSzr%z3U7SYSd%XulMZLft%a9DWQIBH3WMa@jfDWY4r5P)Nmx(*JBf;bfN;mLG!Tv6W@H zS?}|$sGsJ8Z)c>TTmbTgO#lC(?3$zSpC>Z;!Fh@BTOodtt6Q4-6y>u~+y$-To*Mksx#|gf<{v^i|F1^4NsZIm&t5 zQ!C4GVZf%bvw?p!r!J9p@7Rn42*SznUg0$N)t6&YT#+7_P7n|++4B>letdt#w#BD4 zD-+KvbmZRqrU+Sf5o#l+&wcugE@ff`l(8dDch>sEo^Uj*rRDJLPGTg)H^R$GRnOzz zxZN-KK4jzsq^UJ_&l`umN~1VY{O~^OD|g5@ZA*^RE^V zz%jqZu)k>D2|UgMg!8mr^M+3a$`}+opWK$UPY50r7XLDy7(9|q1Qc-qvlYqD?ns?& z(5V|}C4n7*IFHdhHaBZU{rVL7YL2}Zc$ACoC(Bn|SIUicceW=_u0@}yq+J!dW}ldF zpfH)ppFaF1KjUlB(QTkDSiOiAk17Yx>V`dd*-P`G%(@;X50D8y^~V<9IE7j_x-#M{ z+2f$_llii_!z#(+R73!YBcM$%J3q->?cpbaJTvIdY0vVem);Osvs<*Gc(Ny({c+wH z%xkxZ;WJsWDfIUl5RbP=5TnN`XbEdJ>eDU^>ps^vy$DKzdt)IW7~B$HFLL(YG{3vW zYMNj|0bfH+>lq(rR9zPn7HmJ{2kj(Zh)?OE7t0|_S68&QZ&zHl=9@}q>=Z;C&96OzVF>Q6(2SYD^61`ggA|!=XP6PYQD@;-a zvj78td2RwAy{*zevsGd@pGZ1*q^ol>)D0PwplfB8$S4j^vi{T$Oz9N|7;dl_t#s_5++MIw7*bR-<-k~Bc5~33 z#gI2iwye0YruV6KI?zHum!omYx$$VIi7Rv6JF01O~_@+Hy5 zl5jh9!H1B=tL5p&<82J2`S6jUuMtKYopP#L*|CBj$8F!y;of@7*L|A`Ohv~tVda6v zrd;=EDdO+rVoTnS4Go-ueFSAI+owHP?Y6QNmT6-*Rc4%bd&m?%F+O*|qZm&`SIWfP zsICqj-DAfJ%U~v36QH_Ga6$U7s|sDnL!RY)8(xj8GVIp%lj_i{5kXAty|;Wz7`ZDS zWDYnD5JxlY$Mqrlgyc7c@Cpmd3=K{fW5MP{g*3W~8*I#rxA|}i4-dVG;S^OamtT2l z%yA2#i#-zo{CSRyr9LqA2HThv7Ut5RGpm1N7pW{!3ZC_c;i|Mw;P_eMu4a<}G9PKxPhzXHHD! zxC3F^QM;4c)2rSn_4^Jyk>XBDd|9)26N2-#CzIZE`BNE=k$a-cZkv61cS15+Z&iEX z8*h%SHYWgH3~3K0zQh8f6n9m+{l5b*aCFCSoY8s_t_kjJKY8*74DNA1Gf(ajcompE zd%j1hceli6qfus<3<*eGs^WK6%qeN(tk2`J`t&Ys>c{m|Wp^-4?fTfO3>RF48jgy! z$K>r{v+)iZ@Z z6x!r5VZJ*9(VfU9R}okU6eIcyP1;rqn(Zq0lWsEPI zJ!Qm6U!PLt<}S;U$yZ26MD2G2HAPT8t_*2)koYeRw%%LO*||;9e$YszpJ}biM^VGB zTi)?&FG$OH%q_TcyZM;)%l74{VXJ2ZI&;t&G-X)>BfH@@#;6~*D*55CU6Klbyi9bf zOP)bG<(e;vSZ1gZ2$ktPX@UV*X>?_a^j8Pkp`>uiG4d4tdXf~rfwTVPm>2BH4!aFy zO=c+Evn1%p08sXT?f2k9wkO}eF;gGXAP3Tc3VAS2Wg^vq?Gr>UD^{_=)hMakaB9D) z+kk0#*RCX&Um6p}#1TA$^fpM|XHCWExUKiiWMo5?4N*;)row{UoVY?YV0pg6JuFGQYGlu ze3C}_8yHCAqP#VyRt%=96IAibnn%|bHzx#)Li%Kmyd!;Pf14Lk-4SU8C_8od98nKV zCh1d5C4U?T=#XQeyJcX(KFn<^()5CzdY8u#>19p|=q=*|r*i*~6|h6ua96PWk-GK_ z!W^}Kyf7Tvojj@kmFth20=W-Py{SJyGjR)SADDWh3Ue_Zq+3&e&eZ)g@%Jn&2?S(j zZ(V?nPJkyE<_O+A9)Wu$^KNAx9sI#N{qg?z!|wipKsXQp_TB-W>VZA=MW}nj$OX2n z-a~Lo4Y+3(JUsi*u-{eS{OSKo;E4P)yXXV_3wN$P@T)(I(VvO%k@|DuKHd+gg__eJ zKQ45No(!~4|K~TXwenc_r!aXJX;Qati0;=;{0V|C+<6ftPA6t~z1r%NXWuUr=j~Ax zMiB-+8K5tego76`%JiX8!4Z?XKjSdsa}zI65M=1d{xhS%(F;h&{CiYwAZE8`tAVxT zA1HdiyhXKumgybU%rxya>`IeIbQs*3{p*=d_iQUYK+7gU7#&U%ZuGJLVeO zV_IaLQI9!W;!$cZC2h)Zq!(NOdBkZb&T+#iHgB9k(a7WG0(+twHdgAOyzv@1C7GD$qfxb_Z>>Ur} znYkC@>#GYFzjRJDM~kboX>C5tgDj5wUbM-vxWpM=rVquJ4$voB!f&XZZ1$6e=>)pc z^DgLJJ?VDh>|_ED?1uwscY!u-2ZMfC)#mH6;vFWsZjNQMit4foGg}p7vZ{M4wm%lD zkY=41bG!|U2%U+XNd3?wZFdcZEABK!v`g!6(g>RaFem2@uF5bcZYL@|)_-H6NaK1E zePu*&i0-cD#JOxo^Rp1y*^15P#aPoU1V!wZB!mMDC>~$f@+{93bSU~`0ftop2QaHS zp!Iurxj*Y&MGG+EJ*U80(g5zYLvR#1!XAXs6%c-SdU%ajvVSKt($P$fbM+f13{6E) zV{g{f6YYzZI5$yHzZOtl*<@n|gc)m42c(%F({wine}fMdYpu9(G)UI`+11o0$oN@_ ztlKU%lAuE#PlQsDmaI&WAbg#^3du1DV_0+SWH@gb;jkYOKeGmleD7PtnVJG=+SJ8axXzr z9LTs>7ej!)JY)xt+R}+P;oX#vyIjIoZrNx_;iLm~C5Lk~jQ})oSm0dM@0;Jm26j8) zWJ}vv(%C9p$i$ah`GF#{@d)X}9L5Yu{LuQ5_B)hrIY|PW&{;q?01ZA(d?JYuZ4!%B ziI`O_vqD%Mz^f%vHm)t$#|<-{(WE|8_~guKQO%`IyRNS81lNdn?}6@G*o%ag;2@$)C`an-CW z2;60%pH-c)<(;vE@O^Mqcj|$UiT_RAQ0$+BX35ePtv^5#lLvZ0i*2Jew`A=>%tsjU zk16qwON$CEyU%}QFkhQ*-wl9Ge^dOnExmIVA%1cj4YI-(oPM^0)V26|v~k{;L`z9h zRnlNoRpLmM|MD=g+8#E%?P@3-M{IC)UroXh?1=_xJe0(!HLgb(w#T=86sl}bQns1< zD10W&K39%d7T}cS+^^C>{|mDuz#`SVf3%a{lL5W!H{hH6fwaT0I1AjzP4CtpQKD1l zHlh}`#ke1mn{L&X?sQpzBl@l{WnQ^|_e1FUDnBQ8Q~hWyFRp91!rgn_UF6TzQhsBi z3;G)9>JDUx59&k!Z$jfE5Qu-&rd*6=o!PEw^D=P{({mmD-A~^Z@CnhQ&NHlH;@KAE zysbxE?b%jkcWl~)d1+7-2fn{d&I|V5MoPc;c+Na(Tw$GU{X`~Kr9?JPUp7z*8wkQM zM4)6U7-~I19dmGGCz>YYNX$1+824!AC3>WHMEaE*KQyyP={2u%2kj!}I-9 zHoqYM>mr|*vILL$`)+OY8%)OX?=A8btsKo%EuGDbO#g{yP1O0vq1xydKwhU)kE%tv zopQfhkCNsN$;22jMv7zz8UMY7jzq6<%gWuNtc7gg%$N=qWcw>|)cMTmxO78Gz zD#PV(4vWj{$zMny8cilc!)-xyjYd-Rrnb^yH&6~omS7zS`vZB1BRFcfc8tJFTZjg- zf%rf+%(fOr*(H7M-?$qo&nmq*6&)}kfbZcv<+viZyS?alF8AAc(tG;ZPtP%ej+v*q zR@!6ZEWvnaQ_GMmmQxDVl3gm1DlFH6>#zZ>>qmgqZrurHyJA{r<8f%S@_?(e@()XxJZ;SqA zC`oQqXSsl!-f$!&^t-D}C!aAH5XDczqRl8T>{G;5VGcG!VZUZpogJED#L{@c4Oro4 zHWMkp=PD$zLf5xHHKP7fa^nOqajoDT{18xHF8(d5FwaxvPWXZ!_O$xRd!Mp_bkWr0 zbF@xH*OgqQGdYVL@Fc(EaSKxt>*VOY0M%N0oPH2U+#g)Ud%)=Pf zD>jgcLuf?@-&b=ERPmSdhoAjt*~Md)yzV1YRZ!aZ0jcs3V^H4-A+O zNTUzZ=p82U2;<1Zyy4CAH^g6i&b$*T{|(C+Cv1|I_U(E--@kv;1(n>aT!lgxXU=Iu-P_^g~ZQj4o2 z9I#Rjdys<)AVee&;O~OcsN~i%e@cQ1?xS25D{UFw#Lh#6LK3DVZ$bAl-=y@|MMQS=AUd<_8t;uRdB#aN~?&9%S`96)F6c+zYNgj zh6EQC^yn0owHMqV{vv$-*eNs~U`0HT5O^($KG|j`$&5+Z4bOG)xo)3*$ab0SFz9^= z0BQ?*LtPkaB>~q<4`MtRKn=~1?C(2bJ<^jqz$RDI)o>CSmP1p4JFm0~^}kKrQyxcH zj+XmMIp`>@H|k-eQQx%<9SOP#eRgldB%5I*rAh5IV}aw~sVB|Ra<`i>uYwbqX2z(> zMdR+FxTl6&8$_at%Ie1^a~GhA&>LjyW;-zQ8f+Od->5#|+QS_L)RRcsR8#;<_-ByP zzRp&>%Z}e&LM}}=;PIk+!s(IiFmIW$I1c&X9`1FB1i?>m4X9JzNT^ zwo7AUUgMQTx0wk$>7W`*f~mz_rbEfIgU2!WlJAs{MmA5!+qfkYH6Ln#PU^dgqAa}V z_1boz5UYp~gt58qCx_9y+MEt!!Siv}6o6u(wX({Zh!0oawyI58wFP&=y^(Ol7d#m3 zxpF}gC7|iejP03CO>!Ax@+~j~*T&TDn5Ek`31A z6(}yE`D~OL>Aw*);6Mrf*#A=|I4DJW7A&bEs*Z$0&Ih0I$ZEU*=t?+weB7hOe78DM z))n=BbTITTfDj}2O;mtkvukiz;bQ6o&L03evs0MUD*_o1Xa5O&VxLbKml=K0^<^E@r4A4WI=zD~u0Lob`>6F;$c}NDg5rl|prSJtT zW~^1|Ay52*$9!o(XoquOJo5f4eZdN81G?GB7>F6ExKlZBVLWjGsehqC8weJe|0}*c zX}w5QG2Bf7UtkWmQh2;97xm64;TQe5H%Xs2mRR&Y@%%hNA}`1DfBW9t_{0}se4`Hk zfjngY_k!R*Y2E(yfI_iTe(;;*#C{7*xIi%i!O%u%pf5AB1X(2{K8RYKL$e|Qhh$WY zE?_uhs1Nd1>DR?vC=n?B%o5*=TWoKS06(zqHz87#Q1l?C1l+u+#<~HEtHc2oXx_TS zFyokOiM_^TyYq{){Vy!@mUwgWoF8wghyDdNVO3Kd%CuKi?BbCWZ^Rb^XBG@y&86s1 z!dN8EYSr1#Sv(diS;>3p%UIGdYAYP;<)!jG1mboZr7ic?SAZ7p?T~!hX%M>TYUu=@ zvMOfyzT-L~Fmab{hO!XSgqJk#@r}{jyzzh8 zc5(Q8dubH_(jAc}VD%lTn~FEmG#X<*G?m>oCz#nq51xs)pmZFydyZs2s%d!P^6^;J zF}a~1#j8#uVJ5dd#(}r446J^}3p1^3Wnff4! zp|*D&8Dn;Lm~ddPN(KjYygVFx;2m__mi*la7;mhx&`nD6GP=iDud#V_g{)_L#FWxG zVAU#>hFPcOz-LMcvkrnH)3PL#Ev=$SUuJOF0d(RWiP`m%5vAW?ai`K-#+F-FLUkCI z>H33n8jR53R}S3~;kqmHB}8RcCIVKC`FoSR}rBCJT*OA@i7akb$#66lr;T5SIc zthTm_8+V!azP0kK^%~i=h8v%R9>#@UhAy?%oby^@s@%zAN{7MhWRG=!&$$mel|#h+ zVD-UKsL|aL-W{l2n(Y)q>lSr(S*vf*r;_*lFq)`721bHIg|{yc)+(%!FLj-&R8NUC zVU^&%HEDLiGVU;0gYyT_p64l+cfhmD&OWAAJjQ^JClBWMycX$LSeq+oDuH8AkD&j) z#H~e!Kg9=9pYNRgryu6WLZIA8fY6RgkUm64!Izb<`99DDAS@ejO4KEth;hrL7m1@e zgzU%im^XSqgC`AjSpPx~o#uPvx1LF#DBDUI|9yF?zkLZO$6gl)wbAbfmw@#N3&Roq zf~03w7C=C8zygWMwVvGwg>rlIlP4MLCDQL(V2VH*ZNU%2uWe`Ml345sh6ItFn31r5$ z4~y%8X5_pJRH94C7>qB7$Q#t>3>r5dnC$geGfdCm<;j^){(y@++-?YRq->n!VXN}_-(HmdS;3o=RQ-)|Im#!AetG@(l(gv@nr9@YhdC<%E_dMJW-YW<^EUPOWvi zjjeBrF*o1GX{o>p6#+Pe> zufO*^Ka<)BL?HPU9r+=^2}T@&gO%Wh8Ka|M#EYF&`%5tCzxheyxE;a0tZ>u1h2b=q zkcOKnYiTG)5Jyen2u!FWabWDJ)72ei`t88;phO{LHy&qTn<)O2f(Z}Gk0YK=WVI-j z(@$Yu7qgqpBhT`5n9Et!QjM~ijAgOVfKc4W@?>c__At}QOitOnG)G=%nlT)3#j1^~ z9>YyepdP6#9D{M2!~Z^Q4{ITemuu11d&D`TT1iWLjy^LTxpZ!BNfi~wIE6l@oz9(Z z8_}Db>z=AJ(co>Z^of;G4LMERn;=y$(6Bg;NXCUT4nT=@8q9K$26H{15nf{+W3#nF zJML`!ag}8%O+y%ncWfQsOcu1nt=w9@i(2)ryK8(HXrIgnsFwohgkzcf$h^wP%(j7U zpfyo%gmBv`S3MUR%_?R!-#MX|?khfaMmWFQi@Z+8I+~}m4ew*uJ5KQk>bTZ3h&L48 z4_a8Mth1>3g+BQ^WU=!O|Hoq<#Y*jyK8Q>8sjA)~~x znTHxLiQ^!wJ>I?-?DGwMd(+8X=nJZ&AQdZ$Oi`12j@`^C<2|YCn_I3y+(~5s<6#!` z<@A?U%4aly&lA6{8?4$SGNxpUqqc=Pk(>|v3Zi~(>Tu;dxICEyN8dX;-}4W9D8s3i zJF_|#ZZaR+n7H+`)s@S>&30>?!a2B@Py{)7g=jEHA40G|*zpnD*3^-SaU6WSDGaHN z90$koHNP75`yq~s1fQvM-3F%Mnq#jPBMcXv_DavFYrAOM0XKZwdqczNzt`4#7TOUd z^_n>NXK8GmrcPQ(x{hFWAGz_p>`-3h_g?Wua60|$n_nzL3ZIWe{3Jb0;rRSZKtBgb zfu+2iST#3O$>kG2H)2}Mnod*{3V6jOTa4Y&z^VkX-Tv>XXHnjjn@>p zd+0
p@i51ZM}hN0|<{wn=pbzWR?Ax_;BjJqbu-NVvHP7KW2%>03NcP1LL=OHjs zTiq~`plFTSNhZdM1fNSY`V6{>873sTo{}chQ4?%qRKvAe$amX{y+u;`( za4;|wSpO@%Moa$cR%(d2;fSP%DaJ8Um$hRA8E>&P(ryewr8|fvyN}#ESn7m=ZQnm^ z=NrZInp;GWe}HroOTl=HA?w{0)w{-jP;!@j1v|Azb_3l`vSY~ehQBY@HB33P%hMHO z68(zYBaZC1NfVQ%BEW=n-y6qjf#!YM@3dZc2r2J)v2iB!ylr&TzQZ%VEz|o#@3X0u zJz&)WbHEw=(slz`7u{%TMZ$1Oq8jxr5Ei&X+YQmv@QAkC*mLRJ(*yDOFC~3weg%K& z@E~`>KT7)V-j?bATxWXP*)nL#$;w(8lm4@`{7=fl6lFab-0$NdCku~Fr$x8FmNpj> zMg-5Gc%l4iIt1w8Mvr1h28||~D$L`F5ex5CsL8?v@1XBR(hkcdbn0{Dq%ViZ*;zhG zAFpp$JU`{C)s+T>Lx32ByWr}_7`?{TNL0Ege|XVjo}W?pkE0B`32-^9pMRo@nCV!b z@iR|xd~Mn1FoNm1i0_}NT040ryoB%_^RdBMFxSerrTFtXLtN{k!x{d1X-03kh{HJ4 zl8L#ZXm3xHz8lI@HC6wid(WjYekPPTp>GmrF|*1LBR64F&#>vwuSkrs?nDuD{aImJ zyXIY;dOD`NDtjrFH$LPy=QdmP=;2l>E7S$LH#4mj&7m2oBu*y&%PedrpcunAwBX4W zSmYH)jhUvc=+Pa&^ZH~5NlnN4{lx1}F&NGx3&=ZZwfX}%3U(2aakhSi^eJ9VH-)vw zb>F%HlRL|yD67UV(5_Li={rOT(=tESMMjp$`1mKEqi4F+C(yg_-l3y}wvhLDwkWO! z;3qFxq{^hP0%T&>`T^0zMd0i;l1@!LhnVA2Fr~j>#NY&mt^l}c*MPdDcn-+ zoX?&bp)itFtr>1}FXEB73nIA(ssW9`r8JB8=fjj5Ktm9MUG7`4)jJ9pqS??Sp@54u zzTlPYvd)FdcUlq4RqrviS-`3WoAw>myrh2$)wD6W{ZNWnJTPYG3S=hpZJH)-q6(rJKuNic`+eOeHX?|nNbg3xWqQzV;H!MBw0sg%RNW8O$e zUT0Dke)-4jfq(Yl^L5+f{zaho3wW1RJ?V5n6`4y{ZdV)GOSY9H7RxO&#)N*HVFjhF zfcH2_vu~OcJxP*E7GK7RmSR4lg42H3Nk_z2nWOlCe=&Yyt;KPaZtEeWtiZ&JJAfmv z)AeP2hz|bjqw-U5R=Y!QVg_A3lt|)RS2v@DYSw0z#nD(v#CDSk20q6NfX=eyEYt?; z-H!}&iP_Oy-dXyN-xWQMmc%S^AFDHwn)6$Ba-mUrh())NxY5RpW)kts~-TTxhSRwQ2$i53^Fvk;C=@BJv}DYoVR? z`a(^HK87JSUT%DQ;#HgRCRJJ}9hX3T;D+@xt3GMW-z|a;+M4tR ze4&6>_Zc_1Jug`z3!jA=>;+fb-{O2HFjNFHOakLO8Ah-478n(!L(VyItr zgK~Y8@8<%nNir*VE#gug8p4!z2!SA~^3ho8bv}s?@=I((#TBX25_Xy4YIn+>D3Awj zNdqUZL4u#CqiIx|!`-MI^GQKJ)UR%9JBdR19~--~0Y*JoEqGkA0s!R~T5!-|PRpBM z;1`D$It#7BVx0%&G-KmwM6?ti7#hQ;Sch+|x^C-|{WfJ(3z~tY6phoFLfc-*P3}%{ zUsm072@l+49JOVwnk4(>3{DLXf}SRQi%)>JT^)FwgsU0N-(?nb4dyuAWI=sAK$uA~ z`GeT33tUnTm3a0a#G3ug@RjfmpC|89p+XXPjlIk^+99*&@NZ&R>M))yI%x$r}&%)NzA(CeR~ zzI>$DM9_|*vs4SZVvyzuBW?!8W#Sw=>XcHB|E^hmw3IUCi3cm^kmF+_`J1AkPH_>bN&W0UrPAcTjJyHf%j!l305 zx&=pBitYJ^ac0BQcXm-O{iym`Z6G#DQsj+-i;bf!9TfY$Gqt}Du%l%_f`RNHL<0HF zHjGUDe5mWnoW40fwR{o5xX@jR?%;Bw?RLzG)<0(a8cX^j7{kD3_C&rwd{HybHuTcP ziCO$wVF9BF89h6pXWy!>rtbyN08IX;jF|)BKG!h*^&heV_8D2+Nnx|Z2LxVhf3og z5J=bpUJ;qExDS6+BxNOr2+v`@hBuM;JuWDdW4hbcxP|UgV<5d7fV?e;wkWkBlLmyX zl0WS5`5b%9Ol5QZPoCvnB6O2qgf!uhO5T2`!Lb=o_!5j&Ci0^wVYh{Pjl(QqhSc5D z`E>2*7Luq}*bHoyotqoX?syHPQMFc_8(|ic9y{d`ew{OnO0M0~E$2PWc%x(Zm~ut- z-p>VNEtT@mPu}%iK7DctCX~e;UiQ=pi@F5#%mBqLR|Kl?dj1cr!th)gT_;kD)6HsZ z8wfJ~4YoY8R&r07!^nkHw`gs$i{HfE2Po?8hMHWkdj?5yzT1R{=UDM&UgRX2kwTehZ8jXSyS8VYZXUISfg6Vz7oxH15q}>|DUP@&ld9t~&JXJj1Yls7{jJ4~{6fiG!U#-rt zB~Y2T;Lbd;M|qi@Xa${d*rINfvg*rU6pIWoZ_1(=i#yxUss&E&H$0k7pp}VB?w7Mt z?kAOV(Jfi^Hmql70L@IHSIepnoAcroUgCrSpoY$Bthq(4Sjytq6S%>CrQtyPtRs?v zT9)ZW(1cme1BA%M$c%@eFi;Bwb1X?Jqfj3)nu3^Ip_o>kZ%}Wp_)?)uPJy`~*fl^H zzzZ^M)sHZ>)ZND$zYoF|vf7R=>`F*5)x0IBnMN6}%QQ%rB%2wa{Lc^3)tz=Kx|pwS za=KVIheO_L_wbdi(XbZ|F-R{+OMUOVdR-!>G%N`arNa1$li|Mb4*y2{m2rK(>ABDR z{1^X^`u2ZY;^61oZExf0m1M|*UPn;h_In5 zb2i_N*X*C%6Tca+S)YJEHwgYec3C_*V%2f0hlqFyjWvgYiSd!|-Z-^y!RPVOuaM^9 z=EX&2qS&c3sn&}MVN+CCO79P@uQ5T zRl(2GEl0)v7~|U9ks(o-dMc;#((g|y`I1FauqJzGw;Ww9Dz0xb7ZWYy;IOgLUNze` zGUVYgX{Z z%*`lR3Zv7*u3DasM`*7bPb9a;G`H)2z&mAq59#LWzR%muWUg}9(zsMi*2HdsyVb?-_*!FIr5W+0 ze5oTT+;~HOpTA<~F5PASQepPhAL?#X8-*==ig<>fe~x;Vn|~MklWN%-^=#Kwe!!1A z$MjPOZzmxlS#~qV$F(a2z}*wYq9l8f-v3hQsWnQo?}GlDIb|g^Eq3MB4^N=)0vmbd zNPO_#>um83Vterpedf$lr->l)HQ^V*}7AeZM$oNT()_VBw{(m=H4 z^-l}VZAe3dz@h&*;Zx9IJx@}?>M_Gd5;lCy`(Lgwao_4 zcaAU{t<}i|uTd)7s~e2QO}^)HVI})^XTN0TF%T2O$*X4?UEpgAH=Sx5{e2+5W+uQx z`)>z(t)`UZ3dzgPTDMJAi)$lFchF~W^V)VZ{i^az6U1sEkGVSMSRbX8@>~b9F{i;R z6^h8!^Rkw@F3N9kh^!QqmEJsWfVQ$KH#uh}dZwPGK+g5RVZ7^zO;K1(qbu{Q+y=(# zBl+MEW~tAnBb2XI{136ee<8hn;m+SKG~Oy7o&7YjBtkG7cs)j%M!THgvm6>y>vC^= zXbug?Sgr7qbvUgLevj-lEWZ?VOO$}=P)(*d(UbvidGwXN(SfKM;@Cf7*w~!uNpEB< z)Gkj_&NIevrYOThCWSgJ5CCwEbjfxGIK$1D@uFOF1{o!em=|=C(hy6`26##fcFAeGG$u4DmZc43NADSMW?4q_6eV*bT zTc53c1sK%=nN3fj{r)u!U0uq`DP4q4j@-0(z!*g{dhR&(TL$9(&=scBDO+I_+WD0; z>=q3F7=)_o=bYv#V)3zVU8r+47<6Ptebi8zcQ49)-!s|S%e z8wSfi^MKlWS`_Rnk{{ntjJm-LodyLdQp1m0VXlr^jl5K?;$C#kY;(Y2!m@Bv!`P;j zDf^ecxbW#IhFx=5oMKv~4>EsF`y!iZwND;pn3$+S7_qcSlz`*3_I65{hvL}bax zHIsbH@kX@Fcgv6M4NInzR@|Z=9Drj!@2OaMy_uqrh#{P*j*NRt5%kKEdSIfzqOdyp zSs2@~u!G(WqYZ}xWl0b`a@0uy^(pLl#;q2tY}85yT5^^ciTLY8T(Fi{-h(wBmng|a| ztkh-6)UwKH&4wqpj?8MaBu1$%f?7iqd5k#xd6EAMLvaX}68&IMLP-Jj;+HX>k}YB6 zG)GL~7q`~}tk=RHpotcZH(f?u*(zG&ET|)b`H=jOC zFe9}!iU5{kW+9rW3WZlzb=SOB+5u@;n4 zL~Uv@y!u|$TEBERyVYph+0C{;+?%J%k}3xr_H>(L!jwnDZQKPsPTq zw~-kf>U_Bo8uae^^YNo# z59h=1Wg^)%>iazvO|a1Ke@w16wKsP+`(2b4BmS9CWG()UY+21o_h)27b&blfCho~H zq@4?O2_!hdo^HF=J)G@Xh*ok>iAu7GoxR38fRd=r^&SYsT2uzETquUubB_m{x04Ed zeNK?Jc7+Uk<9yIM$Wfc78k)Gl3#;w}KD4e(`crw3S z8vicIJsjPNRX4TNwd^?;4PJWjRP5wBK_qf!q0^!%J+z%t_{V(*1e?Iyin7vK+0+@l zn2++tr=bOL2n<%O$Kq@O$r|Ou#Z?he9D6 z+%zFOJdI&|);<$osR27-e-z=>JsOYIiu6aaFnb5&yBP?*oh0nL&-s$0rlIKo=9|wl zf_N}D8oS7zXo%{StDWWk1N+&*!YUQ9P^EiGSwmn~GSmpf*x3U` zpju!5aB+%5tXj;A((de7P+kLxd~2)Ta!wVw>nrI8>r5>)-|e!R?Zk|zpEunOCs8@m zsBM<5uCvJePj{=qIiS{GIna$%ieSi#E9TLY@6Ey8-P+llDNM?>=^#~&n=Mk8nERZ2 zIW)mWMLTmfrSKZcpYMn-fxZBuD9td?S;|-NOwV^p1%c{-6s~O&H zAmj$&>t6Qdp?+Xp;J!u$_3k^sf_2?SWv)$0L=DKfY&aTo~7(0zKj@DLeXyHD=s))rJlC6wr0NsdUzf6 z0QsdWXb&{y^8(_)5NA6e3s5R2z;Qs^Vo4%hg(hHaSe!!`~jDs z{Uz*Z2Nl$~wu}03$jfW7^+9Z`mi@8^@Yk1$;)3LB5URQO&yF`uoekB!ypUu&hcfa! zFKMsr*_x}3l~#AK(>KlJpjLKt*dz_Ary%(1Y z`Wzr3iKg)FQ6+yzu2Ii%jDCMM{W1z3Yd*Drw|%RtoLwuyAAASJ=9`6Qf0>ZAGLEE< z2p9z2uOg6H0XZSH269bRsLU3k=X=WrxRDSh3BYOy2`udg976}Xw>soI&lGT$B8-L7 zP9LbymC)UM=G(G?pDHcMw(v(y9T^+dQdaLg3Kd_h&3gXWVcjOB>q~*abkc!z73Bn9 zKUsAu7<9PhWqWq%ZuXA*%klRmstU=1&VRlo74k+U(&k$$O7|Ap^yfH2s2j1Vy|aDL zptz+E`-#j{SWGZHNxwZ!-q5lZju$(Wy2-3_3tlWoKb6A0dzfWA$m_Jucl<4Wg3I*C zPa2_Lf8(Ux-D!~F+eXst@)+cX$+`i%kL~MmLya}Tzaiq}>p?oa4g*}RLsoHy@W$OB zCW9*Pqhp^82$|4n^=5w5g}GJ_<2LvpY4wC$ZcCSyNb#+P!2)ra1VC|_C>%=aVqmw$ zA~&b>#GJKNE;y=5iMjv^n8&h4i7cAbC<^psIi;9mrbAjn=O7s4y14Ur&&Y1*$Qg1J z@U`V6myyErZX3aKNr?eL;@=Mz0GG=|hqlQFY1?kKA@KFJy3gcg6P{vCg*k{yk4li< z%NOZBA{0$dCNV1#rVfv%Zx+&9153E-2)iyp(rgvgEG?^BIXaP)aR_Q4A%=?~i7Pdw zod@;->YgPdynz|Akr~63Ie?Ich3^gSSiI1DwyhhX(2>J7^)LPnC?&4g{3o1&KUjMk z_jH;)AkE%+hC9(hjNl!<{jccYxK?WN1t-+YZTjK*8VAV>;mj)JA0b&eqM0<@JVAW^ zh>A9Ly5UJ#Ju@gNJ(UP=3bFWk0AP8pW28>pNI*IDBre}GAWXtuwo!=bh#CqIjfcgA zr(?#syq}wTwyd+TY0b2ST_Q-KHCyB`BMRKj1|K*rYB&f)pP*m-(n@rU>lF$dZh;E0 z<6)NLiVqtwf@-**+%gP^sard((y@b@c?3d{hm^46OxEcoEmog4^Xy$2 zW(Unw1g)Q#l2$NdtXLCeP-6g9<-Gp2$0!%9zw5Gr6-@n$>4vqeNqf+R^?=q%SqPo_ znz?pJH2ptNGlz?m(N6Zs;FrlbE>;yc{jM**Bx<&yUfI;JT^Py*K)EDGvnq%B zf=K$s>AfM&UC~FLq3^3ziz)gX2fV@FTYt=4YZmE7h_^{eX2?A<%-u4OZWxK}OF%qQ zjCQX?r|Ye$+vSuQn7XFGi$gw-0eLGe6W#e{1jkzH?I!>aZokP>oj$zUL&h2G;Q^D} zU`mF&X)GZzaUOK8bUIp1!s=USoKzT|Whe@4F?($m8|FQBEG5n)`7l$KESZQ8p^W^X zfK%+gJQ51W#yC%@J1A-o6`hCoN^@Uji{@I%4RF^=|n5Y>f2XyZ7RR& z$HY3uIEPghfb>gCBu)?$-f*E2d&8=|rd6go1jRUQkW3qsoGckilv8cGy!o_fIA#A2 zCW*{eCg=rL24T8AYiRPIxP235aFWOOcJZJnMWSADZc^c+5ADcl+emtzA^GIT#%;!) zs2*8^WLs4E9V1nO1M!4;3{fmxV}8_n!WstD48zD`ZXye~D2DB)wtmHi70DQgO3Pt2 zi5j1=!AIL$buIL`-OIhoqRtAl+YzW4tQlSdUS9U!4GYdvFq+I%)Z;Gr_qu4(L&Vat z)}BLan)K*pWMaY4O+xR|V{0)Dfp^h-rUh?u<`3fYP0tp0sf=hyq+bu6CE5 z?w7yUH-G#ue4ct|uOJ!03H~sl;P|Z`hQs1KIB~O2)(wZ#eEbi}&Ve}>sQd1*Z97kF z+qP}ny0LBBHgB98+s4g}Z9C1|f2WMnxKyMk6L>t z5XCM|rr!CW+g-zS__=R;e>}?8$*8E097dmhK=uv1KyPIB;Vs5`kJ?Hv`JkQORveG1 zdpTamR{e?A^58V1)olk03>+*B~JL1{9m% zsjwc%%~Lc?LTtdq`OB%}BD`n<)ep_2d@3&`R*#>zbSF-n8?B6OH2M7O*Paf^yk)z+ zucrv-a%K$Kf?M{lBDcgmQB?rGI%isy&icX@-l^tLs}>A+WQm)Vsfx}=ky$iaRMz2i z=e8@E_9}|}n4bgl0){~qBGrqxiJrOzYfek2IDx)>sn?pfJQ;=*2lZ41FR@$I26{}# zExk;Lgt5AfgF<+!Ev$!Vhw=vAHJrre;CKWtPqcU^Pm(ee{u8U z@;PrdNVIblzH6ok3@nXZ#=N7g-rqY{W)vL`n$ZcRtG)sgUlnHT?V3Wb{dsyhm(xU$ z_H0K<_he`AMRoF=xFM4z+Ycs(xwaS&?aCC(ddAf@p$x{(TG~$UA{X!EO3yn^x2vUa zba|dIR`A(FCf{4ESo`E7es)pQzoA8`e=g))Ll=#?-&^W=a;#g~OVO9CLz5(Jy)1Z{ zY=MO1b23=)MgCPqH^&H$sh4{;klaUM+-WwtI!!4wU}m|v;b|HfbI!_005km^034?) z-&nB`Z~EQkK-2P z&3DaVPr`FPJYDt!iy`|3T0fBmQWkG$5#aYT@p|cqG}vK7?MvBp<7$P9miv$IUX z?Mqw7^^AqSz&ednI~R?Ps9+l%ayY2_H*v#*tv>eIH<}ID9w7Ab+#I6T@`DV=0^+(0 zkMwXF8}erEjz^UJP>S=XEYLQ4N!BbBGbe=3+Z!Z}NG(?GE_MvDtpog8>?9*ZcJA2Y zmeB1S)T4bqTZ{=Q6dtx1 zA&^N%z30`^ddw7~b6k=W_jNy-Td%KaqSgR4EFsaMwG++L`tWip_O23jh+-=t!cUjp z#ORxfqB=PL*ES8kt)-{+xE^V#e8h;(ch4Dr7bjUo)z(3kD{rm)kQO9KP4g}Fx?uNr z!BP2x1G&5pqkJEhWL#BSKic&{x?a)LCa=}F$<9!tvmaQb(Z#MWsVFl&PK8K@v%E8b z0TYw1vWC0JWICF&Rn_Pr;<5%u=hs1%D?_IRw$;S0w79MeZCMJh{KnwCzLo2O6UA(b z#*sb$2eNRK2Qxb*SH1&6>tFrzyKTo5D!Khdd!(S&{mq9dCbY4Xy^OXH#d*0E+x)|e45->p*D|gV)jHuju%|yM!70^h+ zwlm(FT%X?2)F1w01X-mc8ag=_0|U4sN;AeubNVLXZ*9h@`GZp<3Rj)DcfnnA7_P6G zJTK{Z59JO0?-6PWj*jF0uXz$tv-*tgFLz+GF0akhEb3cmb%D`6NJ^m!>(aDCnA%ov zrj0W33@1TPFs;G@Zmq;ZsjZo0JEPJt*(Eq8WX3lqm`tn@ZeTAw(hJO$Vx)9r8#Fdi zHc+Q5P9fi9Y}qA};1cx7`Le_o>rcHDNB#~giX`D*H3ck`c2Oe-yI)bnvev8~qS`?j zAX5gQoNA43Sk3s$Iq_<1{4dW&?dZfJ!B1eI;(tU`{3;!8-0btqES;Gy+ha0rVPerY znW&q217UrG^SR5zl^Aw3I32-T*Cr%?fFX`-ne7m%?HI|8v2p%8GcJN%8}nub`i#HyXuE@?(6agFFRE26cYUz-}$P$*ElRt35yc z2swg8{XJjf6vaDZ;x1#Q8KJzvaD_neviP|@QXgNk?k=l5wVCmT&JR3X3LW?vzW3Pv zCdGRq7LsX$xUfz8k+glf_zmJ)c`^c9u+><gTOuV`Ef0Z8T%f_ zf|~w0B(=)i44*mbKD!V`Yt-jSHGNUmvf2=L2WRaHPVQl2A|5f#eucn)tTH0c?AUgr zs(I!>_ZS|-pJU9^>nK_7klM&^x`Zd1C|9Z^v*J;iF#30g?s?^+Fa9IdySz6dDS=^! z2g-qP1~pn1_7MCIivxbs31dHuX7Mrjhx6<8#wf%*LYc^)TlDw@{9@{mot}3q`Nsum zSc@Zye~?{UraHjRo4?EbbX6j;nCYTmv^lVDD7$4*N0!JTxzc0omN=}xt7ZP(bPtsI zff)5jVl5)R5!~Ng@e|(TX3O0t3jYO?U{s)0uT8N@>WMsLi}I)sU)>}_pKRK*o#kKS z91bg^8(Z?ecvym_vTZAiNp)^!!RGiUrBaLsN(0yheB6Q7Qg!&<5PPF6QQRSRV%y_A zv}iGn1*M;|{e_^DdG0Aq1`9U^iyrVd$%6mlzb_FUIO)3~(L>`C?2IbjjIujM9dyG; z>LF$~6m{ob_0$5D*nwYaVIkbuxN1bnE60q$>)Q$`*fVYBA3T?2RVdE92mkQn{Eu1S z0XfQ#$R4628^mGScwsp4(h1&RLgF1tOjGi)({V!XU)(K2K5SE=^o!QKcgvz^m5WM6 zGenrF2PBf2%LgXRI7?{GPV5*JzgS&*W#vYx*;GvG%iCCx=homamqpfAx!3Mbt%5Wg zep?PDl`vRHwIBpIQ?OTQg-XCBa1%-t7-$#-w0euC}I_U>cp3-wMu_Orx1n zZ7hr5BK>nA6o|6Um4NAB7J(a$aZyFXL>g8u(iBIt6LmsHt`Y3fmO`tJ+(RkSOg<$H zSBhC$v(MB$Szh317*Bdy3+2`gt@pgwigOs4MSA%^T69{(`O()OH9;Bw|CzA#pMBH+ zeKSGnKRx>Y*hkQW_WX~Mz|gEfK!z6(Ay%WewBhSf+t%jpRNdBgyycaN4M;|@y!Ulk zb(y`(cbV;Ai0}3N2Mu%_sfFN!9=x@6G_>m26`aMBvlb!3?(-L#=E}7I$-{|dXxhj= zjpmAx zp2yy^XMY@K?hELb<){q%hZGS*-LSBAyIl0J$h>5=e^0;~8Dj@KPUN|@sDsMjXV&oD znA_@Bcgs#lfQd~(S);v%%(OVLhDdy;LM=>n;#E~y906TLJsM-E2tLRpPEq4k)%M9@ z;SYD%xXF_d<7}}S;@6;B;dU=0A~!1=O8v(6+8ol^%_2^2+tYAM-Q1tk?(9cR$_2Tu zI7ilsFi`7yapyM^V&LI_9W-`IFLG$8K`(RM$Tzl0g7zlUPkLX1E;4cjZT6U(oS{#_ zw#GFA6%r;OTrC9>s7Xo9mj1LAOo*t!!@O;_Hr7_w>y707L!H!U(5E(FBv&rX9yO7u zT9uZljH}{2<6B!{ilVR&&+e9u7_Fo=Otx_1+0y)_9gUVN&mnst(G+zD>S4)1v&#@~ zMNB<_-pUU4nvuxJ^`2z(h7mTl8aI?Z9`FmQow5#^CaxKr#l26XT!@WrKQ>t(m@Sjw z@*vO5B78nD_QcSqL@-jI(?3DBkWJt}6OMc&O=k>wskOb`;b&*$1^0Q z#MRF59puah_a}$>{GmsnCRlnMG5eViaVtFWB1_^a-`$zRcgD^x>M3 z&hcB7<`ac^#Ik<)J zUKo;vMR|w?a{lk#Sr~os?4Z7a>99WP7u>J99duW!wO9@C2^Hm!-G-IgFdO5)pFJsn zbBG{q!me;C2c@|XIvDK+xqfx~td7$Wo07ot&W*5D^zJ}^N>5Y`C|Sa4Z_2I8VYKd0 zf0Ur*Wf*$kK+r%ji(@x%}8va0M5+Ojnn)Z|PhN`J2AY8p*RD`KAySYiN2qeS14=Ufs-69p z5E4N10qBq5@VHjL0|-H95<8$KQ8?HPkwI2@-C|9gl?xO!a#ujrEK=+j^2yZ2nWv{q z4(ssp;>Nx#+`v3V45yj2HHJux%mkxVh(c4Mm9}hZ2wIqE|IOeghRVdya1)d6m9o%S zYOiA=S3o}}%xPC$t@RJha!m;Q4sV+_#NLB*Lx^AMpz8I?>Hd$^y7k01RAFKbJjmBK zId*B{joZfFlR|*=@%q6?R0FEl<|9idZ( zi+J-`S72G19&VO4=mW{LLZdcjY}mM$DuH%e>xz<>C06q&n}vv+2+O5Bv{^SNt$km< z0oKY60h@X;g|ru4D*kJy^%>5wobYzWuML_4rNw8_@w+J6S&nZ_h`SC(eN&6K$d=9G z5gk?MxE_s(T@DE$N|czVr^;UuJGsef|Feu#G)aW`R!QkXs1XxU@>SKGx#?-7JeU@ zP6_gTsM>JcuF|j=*tdiTA()T=Ox;|JmaS&Dn3b!V0`B8TCeUS2$GS z+u1le=S(`CNxf?FxCP2%rOgXh%2yhuV!vtv(-9zs0T@draX}VF zWJ3KQW6s!?WtD9W)Z~^Yo@L8~;2O+WV2mK|W{=qd9orSt&UC@^0+aMJ9z4vFmJ8Zu zi?M>=E-axJYf#>l{nKKM!)3|NWd_V;#@9d7={1(&!`zxaRdOA65W&jypr??7ViWWd zbEZRn91uEOHl%e}1kj>^4k}sKNe-CNZ zGb!ioUv&p#2@~h4r(Z`LMV`V7d4!5m#!*P5pqD`CF)rVQp{l0sC#R~$bE2}rQF=yU zt>NQ~g|FnmR{o3x%GyuW1MV87AuaY4usssWkgJAd%8%@3_O#@pQIdiIOYa6EEWql- zxj*giMqUM&lQyd9W*lUSlr!|9~Cq9nIG`i#O8ns4VC=I#ml2(0D z#2((Q((he~JNjbfGhU0w1&M99@+XYd>r}Lr(}t6@>Y9i(P7}&K!R}S)Wx$pPUH8yR zb0sLL__B_ACra2;l_A{;eJin(-r>fh7s+NPNjg*k6q&f1Z$YxB@re(kR3-TZihj&; zZ+j&V!&0Y&^1r^Nigrsj@*a9i|0G!mK>c3jjtRws^-@BB@c1L$&zN2ICM4^jhSg{^ zKDoPg6N8FN1<6p*0?I2kkPpz{6T!aGa=vrXj5uz@V^B2mPHcLUks6&TxbUlWEzeB4 ztcd22!E|YFqnNf<=xkqhY{Vw)mw*SoCbAB*aJjuq`V|RGQ=V@8HeH&(+B9-#g(q5R z6C9-R9umY9*jgX!%WUV$6XY z6*f|#s%!mb0B@s1dgWvtt%EQbnd${~OYy@DB(UT8m(&eo6@p^yllq%^mW8%>gJ%RI zze7jsAL?4|baU0j7?vFng+tkUDpJt9%=_?@T%j`BU0V}4i3Zn*SlR|0b$}dA_)l|r zG!P?fBo^7QE4=#$kQl7agxw`p$6C){Xu8m??}L(`H1V*vm;ypEKJWHYqgscVU!15F z#~;s-;2=HL1s9P@SwHGG_~L$+$uFSfevvxba6y)y8$(T6)(?Owh!|+0PNuGVRn{%q zY0~ytMA(548M70&TvCCdxyfZDBnvr(Klt$m5RTjt|BD120Vyps(&bE%a^9UgS+giR zjY_d+rWa)j)DYg87H^~+7FL4D&j?00w%68OqHwGIVN-B*&Ql6MqL87+I!I&WRNNZh z6G*U?E~dh7^FA}Gx4M|`p!HuPUNhA^9jVD|Jh=N}X1ncgKRaOjv?8?Ys z>WdKb{EcDQlObCg{~lrrAxyPOwl11&b;rVN^_DNJxI=@{V~gZ5IB==me-t`U`{gsL zc!d|S$#c@VfMt?zy@ zv><0%kv~F1xfk9_YA6sKRs;WMs3fj!YY*!rAuc|W6jKw^MY6(&{X85D z$?RyW zw=B2DV%hj5mq_(8r`_@25A<{Izl<#@0opWczm}0Tm4B65y9R1c$UeYHgM8`*eHl^#jL1sjfO%zJ&0jZnrH z6P5EJ`p{1fmEguaqm&%A->^PHn5L7W6I@0md#viJIe*IG27AIqhNVQwYpOg$M&S}} zM2CO3SL~sUsQJXnP|pw#JNoqX*`syP?ed`Gu9b{n>Xql#IPl42b~ z)H^P&vlPpV)k}<8)eS2k%Zu%?Wus>81m!VLeSK#dVy#v0*?&%^dhg%KO-a zg48bq%F4^hQ?P_5S6J-n`zlbjHVJ)v5&Zb)BgJC*oC>HCw~d_on>H6YZv5&kb>Z#P za_N5Sb^--yw@%0zzg`qVET6OOCgNA)GkZyDTqEE_mm4Lf_V7SE%s=gJ~e8X=->_~%eED2PX zHlzizkIIk)d1eu{SMHYB^w1M3?f8Z&hxZAN?10I?G6aMV&w4x0{x)EwJV=-<31g-h zQMj@Q2-A30q_%&ucu+9uuq>+O#b=Ec-Qg@m+VENkc?8#eaO@$w3-PUs-QzrrsP74M z;A@atVq+4C(^C)NufU!FbAi zXSiLYmcmG#^*|9ewAVxd-bVcX8~LX1tOT~ROrYIrDNToB+U!i8<^Y_bgx2~8pSpVe z`n`6@;Qht#vpd0nT+SxDLFo%FYXoNVfZh-{Ch)&VL;n#~&-<6(w|^YM2|o})(f{9P zM)SWiX@%_V9bEtW8}mP&80CKZML{IrWX^Uey`(UZ(4@3B;3TwVNBXJ&qLMZM3XEuv zT6TkV`bO9MhLF;C6sWM{4(JQzkmn$92%4(V`1bF8FBS*)f6s&leZZbExiHd}w8r?j zW}fZmCX=IW@!lcY)U_zLf*Y#XpHDmBfe6qtdc}*fC$>a;k+eonNQJINVkFQu^WL{Y zvV&GA;a+6;(TQ*d&sbN;7z$;diE8^7FKVJ|u`zt`s4j(jnju^aZUXpPNyV zn}F_b^oJ&vRFt%M3y^#(JLbgOi;x{b8>_BHNtJOb1qSl2R}CS8A>2mUff0c+BGor@ zV~M-c337VJj=$Xo0XSFho=63u?g2nD{M;d*--}|Fv#E=w4_g`cqH8X_69VouUR{cr z4cE5C^ycB(wuhMW89He@`4ctATZ@*h$8X2GW`H5mCs$}&Tr?+KehjSi^*V6Xm&x*@ zDR1=Ut$~k~hAEredE{d>&sul>U~V1*MIs;J+hS4!ml6_x#EyRCeJGmlE~ergZgss~ zYI`T0y_2l{zx{Ih=P|st&QH|QIueUC-(dgy{ZZ}kYJeB|Ns>(Xf8tgC?}^_}nfkBW zGTZ~{lOp!U`874w`+n8?4j?9mrbU9{vn75&u?`>-LP-dz8%Ux>l5Jwjp0h1Cyv`Lp zL`pT}J75i{2>4~#x46hN>%P+b?1%9+%W{2@EhibUo80SLF-?i(@|W#@ZphA2@nl$$%QY9~)o2)2)qF_$v0tFTdbG zHjae=Tq_p0miAxL_CeYsqQVIFu#?YyJmiB7g_J}Fs@~Z9e3a2 z@O2UJRoMZ7wJSs5Gk?~%0)1~ThFf3s_1tTIUH&Fu(MZ%7Ua6U%w+&k8e!UXypso;n&_Cr0xfi-M19AKiIYSj<0UbuG{e1z0r*r>rDU;5u4nU+&bd^#$_t@Mbt$gJz|54Zxk&^mrpgP+ zVSN&qJ#e0C58{l`{7WtM^l$SQpOp!R#s-})is@K_E-$(R*C@bec%nt9pl*qFe|CgM zk*HQR*kP1NpC5si}!L>tRCSmhGLis{9(sbv50*DLu?B)M%+D7WI{s zv-H&!)a6qPjup&Ve0_%E`Ge*J!PS$wY&7+b6MN%}cNTLkuONrqgB=#rGd913QgZ@b zY_-g^rad8Snl{+(W131|H93x+={dbjTNnER@!#b{|g4UpFoN6%A-hzqN zP?br6Vu3<;^D=db@b5R)ZOLe)QIc#Cu+MMa%oa>sEnwwDn}>NyQn5-)8k$V zoy&(%SV*Etn}}gX<}Qo%rKU5>*fTr&Y*cv6<&Y|yvbnjsrUkaM*siijpic=M9hM*` z_3&a!>baw$Pz<$nG>Nj1V$D3)?f|v=Lw;TI#H!Zh(xTPkWpecywJ220^%64`MQik( zsn^M<5_)NE@zRANNinS2@`*!J${j3A`!D%k5_^(_5!g1*LW_hqanbQ{#fd^Syx{kS z;-Ec8bf)yBcswQpgwV~AI2Ss#i3vxYLo=`=;!8AdC6pWa8WHVbF$vPvWpX3f41yZF zEPLs9Fl!p`vES@MjFfR`A=c9BM1`T!jfTkDBv0u`QBI-d+_p+QNtjM|^GIQX=WOU| z){p8I;LZ{&t~O7S;8ocTEn--v7OiD5@uuBS2gstlQWzdwnI|iPb!M%H)aMPhL_OTP zYH@tnQ`~?70rU0+c3nztw6oTQu^MgBS-DG*c(c1!#KKD}JK#m;mqZ8fUXhd~QRm|M zro&VgsQk-fRd9dAJ3%(|(gp&zZX4n3LK0VPEGI$tVDd8Tt)Jvd^B05l4Jq^?!M4$W zhxQ9j$^zd-YO6w%T(NU2x{tIBY>s<>8?uBjgk3xglkAFZGoS%&5o`5o91TMnvV@wC zHuI(n1glU4%jsV$MI~6+5By=kite>gVos&aRitW^bV_@O0tB{57FWl>r%>bRG2RC+5d?%Ieli#V2;$*O2{0 z?OJLHy*tp`zzPyC&bJJrwKvTZ&eZTy%rBnXNE5EwMoCbq&-8#lvA@eH%s%adGpCBs z+e00Vkd%hnh9@-7Q2R5@*y5arEz#4^t%}gK) zT#{&&Yip@!X6d2S66vdI#X)`7ZfT=zdroTBc+oB^Y1IIiCF-%O?pOWz)_WqPXcE_h z8&v6NZ>=acPJ{E?{CQsl3w#ssM7s+!N+tiqeDCS}F+(+a(c+oHL?N4mN3=}angFWm zRBjeD1-fesZ4JvAmTj6wOThdrjQ#0K{k(~SVt{Om0o}3d6>K9@|CLYIP z$xV}_+gg*Xd0m}tl5-t3&w0Ox979qgEB0sc-3<=*dod>q2-5Bx@ISQq5Tkc7;TErT zErL2-{oroS621^rmuiUCKAApsHDQ`H=h2(s4W-}4XCg?4>|t4ijvdrW`#GBGQbGw6 zl5S!Z-M080E)|%y4Y3b`jz7|a=!$_FMx~mOjD=c-c2Mxyz9$>LQCthsuvn3Ro{FAM zQJG9EF{waSxVv`y2KT9vWS1?>1d0so=r}ukc)hr(mDdVOZAZ%~X|)u>W>=nQ;a;8{ zFjjwxjvjsyeWjDgA!%lqwP{K)@#cvnP^fdbwwbClS1qfq*hyXv+o!)^dn7eABhL}5 zho;GRKzmizcWmw2cB$8#rj_!EY3G#X-TR_8sc@5cW9G84C6Bsqk{w%CRiE(N*uILT z>mNm+PHG?%;9WO;_@XsR{^w-lGjEjaA^(y`}>y{os|y{yNpP;VH7itG5Mx_)FLI7#cWnl5F)D>c~5ME6T>bYxW4b?T|H!-a%v*iC|>Y(vXt~m zv0PL^ic0Q8n|QNyHs>5fF!NhJClHT|y~~S@P#pHm??41uB}Ym_kb5R0lgG?S>GtA7 zE1F`KmU4`SmY#Wie~(rrNA6l>e|t8I&&Ao#2$>z}c&@9Z-Q&LO5c3#)dLlQ+B1#~_ z#my;?Y9$)JjMG5Z&>8W49t{)4PFHk%IAlhK(u0aTJ#tdc3H-3m6iUD$yB8vHycsZy zp^>>~{X`o)Rh;XZwTBZVrrzGkt(=?8RnFX927`=DKP}oXHKrA2n~6;V%h=r1*1d(c z+GK!4U5giEY-dyga8a+|mL8r`OkuQ%I=9?iRdEh(pEq5%O`u{&@l1+#K0YFzyNim( z+#&62$Ndf8V78+NV#u;K)*`m5)USGe!Q`w?xBc_PeOKz4;lmiUZGiNoM z>(-;Qv8i#buUBi-6GRyIqTrVXf*olN>hCKZ#82Cwapf`k#Zz68o5u(1;-OrbP}Y5k zs+hO+`?)Cg(9u+v+~2f$&N}DIwPn>ZX~9QEU2@Xu%(53WZs_-opgl+9m%XsS-vbRm z(p5!_*O{*tHU)$IV$(Wb?7GuFkNjtmut)X z8^voh{7HUgLy~#Nit-v%qNc@)swQGy(aqbG73LcRb;6K>hXg72#9{o80($c=;4K01 z!l*)}rLBruITkPM#!H&lF3JK-`u2F}zU-y?C42m9dYgS17OWj{-CeKSGO8~+-SxI< z{0j4%aXlA~>VfB}XI$Utn|Ym*eFN>gWaZo3A=3x$eb`iFO)fK z@`qA=k@C+ChnKxb`qV@#$Zn_Kyirm0#MQRbmA%A#T1U-Ny@EtyaJ-aK^%^5)@{0J_ z-QlSQT;M*{j$04!hRi6+#0BSOu=HyTBr9cj`WOwjbfFVFz#g3a})6-aWYWPTUzU`xd5h*9}|wlHc7CF4V#-D69$qGafL&@ z0rzL@So{`i)TM#G?*fWT@_y8f%}VTPF#aSfI70DF(=H zpZMwb$SBrAWx|Uy}Z#LK%5J`U#lE6ng&pa8z_3O6}H+)+atvjAu&hu-cG7lw549`+4 zy}OoB7a44plY=(_8+{ll+6=8euiFtGvlU8}aoYHjGmJ$Sxrz#7oF>0@yzQl_X9U-1CVwct25?$`Li}g8b1RNOiMzYT8yn!ZaE+FZ4x@Kov39jls_wDyX zDT6jty{5VOdr1m#^{p|vYh{YbYxzPSeka<$Lr9qg=Xjor*l7lN8-G5W#LrZ--4p$K@Pd0y2(;b87zjGo18iV9! z&IPM{*hAX$Q9U^H9dp&-hgqkwLmtX;Du+Gtu)9K`H=>jwublTjnw0q~Gvb0EW%YYs z`hyq_JM!P~zPtEP1Kx~q+u@Bjgc&e|hX3LX5qx6!1cH=bRIhw^Ijtz3W@y$u*@cwt z$g{_son|T%$c=~`KbWPk5OT~SLlVLqGlu{)4;Lz|eA5o|E{t*fK^VS6lHEjDoXnAs zOL1L9nFzy7;RBAZE$&;0jZimi#=E#=<<||%@pHI-18o9>L@(evUokxIY;jZN>pVGt z=RXa;2BA9m&ghw4lub65Bgn&kP#SqOBkzbrf!6{0I{lKTx%-v@y5D{$Dv0;jU)5$(oI4(&y!Ntp}Za& zvSCyrhjZY=`B6yWsPh9(B3m=nA$uwV@?8HGDo}CcRlnW zN`hf&m~*VqZ=JdI)Chm3i;_EU3gtL0!o3iEm=B=hKY*t@~ zX@MBKL?B;)Rmav(Li)zzRr2i=!p{f!Nm@vZ_afCfeU+GEcu=g8-AUz%$3wT za+fh)#>|i%*6G5HJ7G>_g4Qs9L6$aYzMpNZK6Yei1*{YCJ#c}hK8exXysq3vAd}u; zc7fBD^LIeKfoDy+EjG2eOAGw!Rr!gi+L&iO^FqlT!#n9S@H5rUu-@>~=0f-h;>jmn zZ-(DUqk(W;4R5V=tKWVH(3R<7{QE}Mo#uMB&5@8_qG6L@)h zL&0!S&;(~|a!cM^7G|9K< zzmd_RZnIa(K+?atH=Spzm%49*o$}PD84YV z@Cu8Xd)CYZ9t;(RrbrvzJcMrIou_B03cmVEN!B9G*;C+hL!{L=TxM8@Ca$v4z7Z^8F?1lI z|0k^N19`dlJYV+;)bV11HNYRLbOC#?SFh;m2VdTBy~p09i5*X$L17h=(3(@Lh)e7y zX+EJlG^vc%Wm$L?h61s9t0Zk^A?+|xTrk8c%ZAU`98=OB2QxuD@=9y8UW*_*MNd&^ zhBT+)XsO-TLdb=)nIi&u1;nsgfV*0V=^=#RA@Y+Jhb`wqE)Y1CI?i@Xv|J-vCGl2% zZfN~@UA3GqjPVFeL|f3nKnlXyI1Z7vjQD2)6v|d+oFfu^mB;qHtfjVHe=>5La zINB_Ehoqy2ZfwG0d?|CyO#~QbWjyuOkkd}_%cIsvLJ(?1)&aIvl~uv2eWj+Cn5PfM z`k#e852ATjD~>0DuI0!$k=CDAtdQ31y195dTPB0{^ik?N#fprvVWRvHySxaA`LLib zXf29&2|#y7I0DFJ_re*|76Zb5C@FU&l*cZ_6UY5pKES#&nEh%#R7?m)9j`hdG$ex6)EB0e^)g_XP ziYN0`k$*Ir*lA%(vMgi@iLvzhuE zcBB=Dnye$k>{?2a{5mfrteVD4|aaGAGhPDxz>j3fNg7RZ?JzOO&H9+L^!Uubm zV~qJm9=Xvmg6V^oKkyJl{ug!8GCeYeg{EvHg)W4A1l61M0A#FLWqOX5M!k;he4N6g zQpFBjUMNlBTF?l#IfoTHlvl$jeks{1#&qtEzR}`G)ju|%XQ$QPWf*(NyOZ5Y z*0HePiNmgksU`k^EjOZLG-pm?+Y36gWzF%tU)|j9vwV~wbedDi6twA7Pc?RaZ>YzT zw+4*x1#~AyT5=O^g!V7GyMgdDma>KlIMfMMX*7qjlf zH}LAMh9QeTI?juZBZEIK!OrzYlR0qvJSF$4bFy7KN7Fso7QW?(79bS0O-42`u|3aD zac(<`ZY z&TsT2AHS*kf6%x%1-L!J{1Z+u-3ZmVuk8y%bp6}M#X@m%GYq2E@-BwIVcP_$pAAIafJs0&<8?b5}|CwAlCwBWkg|g=@)i!=AnNWqieLCf7la& zH^mUw$ba?w%}W>?Vs9XX&IRViC%6f+<7{FQL4c_iV!IHZ2fLvs^wS$-n*3#Zc|u`5 z1lx)*&pt$S5Z~)ieH)Ab#r2L~Z@Of1$Ic4V-MerOZ8pXWJQxP#hp+`o-gV|j$?rL) zAOh4pq9OyL&kIthJBO(iG0>#e6(K?Ar(LMI7HI|>u|q=#l_9Di2iA}ipk`EmK!zZr zQSedP#76^~lnw*o2S7|nIV8AALqw9OB19r^!G6YMaA?IwC0L-SL!6vKvLPf)*hkTo z4Wc;#oS6v7P9&<)S`G43VUNZLx>Ohg@W#knB=T{KFxj?acES>d1tD7iaIOix$P6UO zV_b4w{EF0i)h23qdUFk_*TVvtWNDh5(9ekcUn9e7#>ym?#J*zMuz6jR%_ zZQHipPHo$^ZQC~gwQbvWd*+<)>bpE^?Um#@SxI*C?%(r_V~ozmkVM<50A-kwzMY8k zsM(fA;W-9xXh2y?X@hsPp(k&WfOkyT?WGdE*7ODIfp!ls(erCV2@N~bt6Bwx7vSCx zlNKe?w18YjFMo)RS=yvcpT`ZN|8~TzOjRg@rBB}?Zii(Xv=Pn7YqvGXTom0I^a0sL z`A)l66HSK8PL~1(c~Tuv=*iQITdcnv_gD)biswU>Yx;~g5mk{g*6{58^YTTu`H+jC z0Y^B-OsIDmlIMmV64_0!dnxAr#D4wqiyHZlf+`Q_#PEVWar1!aDP*}p`s5eF1v!{1 z`4ipP=hUSt3E%aQJ-4ta>VF9&AAJPVN%!$9(}KyBrNt76U8d^5BOPqZ@U2tUog6 z)I@Gvn*VzKSLH!^HUSfx!ebg5;5jO*)BcXm@jytL@7b5M&5tJ%WqU~7I}gP#ok-_U zUeThC)-9k5-Q7C46;#^<>XQO~@ z*neDN`O^b*Ab}Bb^gVPaCG3OzJ_dwi&XT^dm~#6~r;6?!rL`?Y71BvSw@%cDOvrB% zat<9IHBTyq>+)2Tp{l{DLlPvu%K$B?-!z2yF&ce1jRbQF(An4z`^1eaIqMVGjah<0 zBa{*(QC|?jB`gN;JMfso<0&Qi*~&-il%Y)3D;Dg4Yf~=e6^-!?hK_=hdNNjMok>Xt!?HKq@L~AG~1?&|;*Adav zXxUSbcR8c+FG6f>asKtff5n|lGH%yrM#s2Vo1^gB)lN1#BMvbRxvT$ZDPN>tVFrsrf zGkQKGHFSmZRF}nIqENKIP{lEdT}?ElGMw{@wlkG-aA%FtZd$cjEwrjV_p+IU7Q94O zuavV9GzU5d2?w|#-pCS;-^mpf`1+6BVLI7$`7?rnHXK-Q_It9HI{zw-&T%Uo6@In=XD?u ziK=v+2;{vGTKgSDI|Wrmk3VBnaGLT+0WJBbl#8Mx%`?%8f_3x8WzjM?#gIDUjc&!t zA3;$f0oVv*S+$i`wR%1xqZkEi&*y9p+bRr3$_EyPs^5&G1a0x)-tH8qt&1QAK{JEY zvX$SoX<)&w2nuU&=7enk7>gPEoF{kZfVnQf503^TpdF?gg&YPIOmZ>@>v z20jsM>EkAV1zu|wxJzRV?o|{WbkjU1y&%dM%Npan>_8G>T1dMI-d*Igs1F>aGCf;5 zD|F191~fz2{Q@a%9GmY~d|F2X%wQV-`-oIhQUB8ZIjCS#P=Z)|gd)1=K4YO-6`pK1 zo7JAfn${T*gm!FZ1?m42j3aO4TLC?g9F~;*R5w~sYKVa!K~$g%RGb6$Cu7J*Z}KL= zR3%r!5lv#o*8EIR(X_KYibA53OyEwIh4Ke3r|NCkO7lP1Z$()vveoVMHt)G5dd#R9UB?=DSQzl{tFlPZ~HU{&C` zXx%*r^1M^xJHKyrp^3g6r-{!`hzm}8J)~{6aRYb0`q!ntTzx5AA|ISzY4GP9t*yv6 z`zq6=#_%nVotSZuHU<+4Zc6`oh!CH;N#HPp)4oYMtSZLWLh!wW0iBmkNgW#RKi_li zU$MMOY3?(+J&E?ij!*1?olwCaUhFlgp4{V40XmrRd|aU?m3s7N-8AxFuV?q?(N z*R}JpbGwLtz1<9wnFYcPz5%-OaoZJ_aTFj`81@2&xkoeb#rZ2YFrzfZ;x_;bm07z} zKA2PaiVPF3BuVv+a4z9cQBQPE%UFIsYr5BFZ+dM{Xi;-tfBW@+Zg|h}W!Y>6kA?Rz z&XO`5b9(=7Gk3Dfn@f`BW0doAX|yrzo?o1@D<7ZY6mS7#vl*6^-CKOBAni&K%G38qnu?gJqkEn5E*VVcrW`H%C ztD8JEQITgzCnzSPt;(wFd6=f{8zgulGBBdKXZAVPd9r*DkSmV=~nSNV_|NQzlaVS?FXyX%3czBlA!7#f;r@%_EJXne2N01PW!iZ$F zx&2GW*t_nm1_<`hc=^1dYDs~80>S7rM2IR`X|FKnuRr5YH?l{aiC;6K)7zd(`2r`nO5Z4bw{%3KVI#jb{nn*5UyvNy^7yvNcOc z>)H`7dR7I|zF#$#NY+4j8TTI>{HtE(kyZg3cMS+EIj!lA$Mx|BK+81MNu?wSf6wFx z^Fxc3tGOQefx`y5*)XV_a-wE=K=VB*1=&D&vPfokFhZ_Q%}*;m|YwJ$e+rE<`PSZ1ZJ&rS;1Uc;FC;S*c6>6(6c zpsm^I*bY8HgR05yoKc$9sLgsEzvj6Y2OI}aA~sj8>{4^ zS7F6KK&-F|4ZJ}@m^Oz56_XG2yW5F)np z8=h>D`(6w6*@~?_;3u%x48GBCUV9;5J6s3iOpoZNK0pw^1d3nJ3@A;X9Kbu&N5`33 z1#ue@8P`U~g<1t&)*;;6KBp*>94x{BIZ3$m8*%O3p#nl4l3A@%Fx?r&gu1KkKEPmQ zN`t6jTZ3r~uV{?u$-f;RTLf=f*(&)TbuX4a%@E24IViH=+bINUiAX;m!Pv*p@_ZPo zWE*xoo`C72Y7B-!bP_DYx;w_vDhOp4&%_|Na!U-Kzj1DdRF#!^F^zreAcB@=VFX@T z6^FRu_Px+LICld59=y>HKYxjG@C9g}l*ZkBVw-UF1_e*o8iYS^l{tKaTmA!#bCg-u z&Vp{1b?%yM`EfZT;VvTWne$-eEOg&CY@=*1b`Fks(7j6D0P~%H?ZsU;et`=IU7^qi z(~fHhkR$aZA`{|+_Q>yj)!gEtY{T_U%;UNY;5$8wlb^R0x~_IcSkS8BUfVI`Fuwzx z?I0@BY}AEL**vA3VAbJk{>d=%5>>L}UnhMB-+d=PEs729e+NOYkc)8?3fVwr%jzyw zzOj4er42ji%{R-FOSKvGUHuaQ>6_>;=T~dL-HV)8Sozj60x}5%$wBs(QNwGaRv|kc ze@)SSgvs?s8BEKfqPQg+9P?;UfKarlKIgCwj+W@1=a*EsY}RGDI-btcocSYCT0_JU zOi#anv;WP*YdF*Cyf(j!95|&|*yK}b!17gm8W3`x#vw^piB=XZOS)yPEtg;;FyiJ% z+eZ(*3a@E_z3|M_ZHHG69NwsDR%hi5uuLu-t~Y_xtX#0o`|zxq-fw|!5YmfcdXx#K zr=vQ4y1>8hlI$|Ie$MKxy0Lx39xU3mD}AKiC{{~qgWd0#W{Wd^VvkG)xjwAiHMx<8 z9YDIXGodT>GhFW^x4gW)i*$`+kGiL$yh&<(0k>olPO$2JnukQs4A-U@>zBE^TJsos z8%?(?l}5ReTu)5T>73PWV!Dw8ny*>j28rc=$>6LnQU(^)(_^rTaJu^&a=mG6{-HDR z<5&d?bm7e3Nl$BRMe(=5e7<0b*F)HiJj%L9^G}E65+kwAuom>z^S7`i`pB_Q2?rKv zf@*wxvu2}ThKzc?)GjSqrioc%{O3JIBkQ3(3i&`_z2!FD>R&U7Y`Sb$Tc4vDCL(9T z(Dnt&69ap2qi>->)-0ty$ zirT_kN6N2=?;CA4A!g>274aaoH!lwE2$(SnR&s~7c!PsJsS)oV;);92UftJF$-V#f zZQY+8F#PQ|ppPlqo|lU&8?GL)mza1ql}vx@ioqQqkV8T;%P-Q)p;E5EUv&`p5j}fG zZF_XZSMh~|H~}WkirpvH_VvX0LWyF3Oy0Bf4_XllH_6kpt>5yb3Ue$+$11#F<}^!Q zp;Ba}N0kq?e1kD_k-R#B8Z~0I2rQXIcm6}VJiYcyW3?KH^H23fn1H)8#nO3^%>yzk z_Bys}tmp~M?kVT;eoBoDp*L&Men~Gt#uuvNo5x{NZj^yf$n*>CwEPFmTf2-_=XXdO zHvRfhP&h5ly^c-V9-~1E6-r9myg@q^u&nFf0S`60w$&vvSoKs&efuV#s=RPmEM!-b z0S!e@1oJQBhY|b;KM7tVaW0zINtCF_qE#=zx8)0Nfk$WDZq5#bul1U*u(ogN){p6P z1ZJAD>2zUTuN0MjW4Q2s%xI z`|R77L0Nz8qr6Va{J=`gd7b9xNeFwdtu-(W)8UmfdoS-%*gHA}rc$Z6a>vqCNZ7z2 zmYa6)@CSIr3xcI)0$72w=a|GLGV1VM!2AYbpu)ooS{$d7NCWqcXV`w#`W)7tH^y5Rs(MZWdg%yJEAp zF0XHD*~Wi1J^eYX z$3ti@W6QYI;ByD2+qn`@5+Sws0WN9aVWHnGr>ehO~ z2+H-(?B-b9sjNSNbh|)L*3C=Wman+@-4hA&794um_j}lTObHNc#(N=byOIEAjDWk= zW8Nft5twsgFOGp1LHFO0vnOL>sw}q6`4*d{yFIeQ-ZUY~F9}AfEEFv?x8WIA!bxT) zs33>^6}vO5cH?WUSAv#B0fI zLk{#?$#MHNziT@&J=!euay?N%HZAqbJaH0k(&^{CS*4w8L%m)=S<@1WN=WmZ8y$f! zH^I5s)~5GF7Xc5&xUIipfoAv?fHvd)NP3-{d=3enQ zLNE4kf76y{3nJcfxD&saJs!8_mSaC69NBcPspMQS>wrp@h zmqxdUieTOy&C5?D+XC)mlYhPLdIiDEmXNDE+Hl|d^!oePdnaFr|MiT5uoqPOHJ*a> z=L%{$1^&O7#mwuKc1-r*-wNv^!V71`?=NJn5tkMrIA3|%>e}jAq0$y2*!fKc>^uxv zac1o}leF0>@gQB%KckF_`@#V;s3N>v>$5Am(JMXi^TZytuvj_oJWUl9=%m+zv`gR3RS! z+KiK(Zj5MoFs>Rt0&ktd=|oYV{+q@H3c&+l0Hv9M7<9y27gi)9BN)%X_$hBE7xL#v z1GciMWA6et49*P4(QRvie~OPIet+gLWBgU49Yi+~Yduig4Ir zS`6bmY%{W$z1W7~Q{4KS^dWI9Pd9yg-WK-5itRCA6Gl5UQ;{J!*L&DTlIs?~urtcg z1zU>{sq_qv>sN%I{DT;&RZ(bEYwF1lps9|;B;q#D;Y{0%v6p6vkvRB_7d2ylG~*9u zgd2dcw)zTctIpI_vPlBDsCACR&T9Y-(7Dwb%s)9ry2xw7Ijp)rJ%;aTAjFD>#xZ=; z(=&$+bPmSimn_l6$||GG!paK8^r3=Yjb8+5z67C4sL1DfplX>mbP9w_%alo+NnCBc zf1~P1=v{aEpsb*!7bTd85lO)brRKtAjP@{I35REPFeqby0AMB>1jPRV1whcRqyd$p zgUTBs3$`;LEn_t52QpyQFh=NiDnLgAuve|A{Q?1kZqw`-x{RoUTB84!+h$Ga&(k;5 z#}c9z)X567oS7&!QVMPV{SZe$r%8xy0OtA^MEY1pPsngJY_*azA!<@UIhY|D+- z05F$Ud!P*??MYlVT2nkswR*Xz%C!?f^Ci^*=QB;ro!$ZIbEU$J4uB?Mr-mQ49rFF| znj5Kjpg4}eku<5%y^E|A&U~fb%Z1=3`tt+Pi-3lLtqb(#p7&CTUY)Eh^hIR)fj zi9yTXXU%6@&LXnjDmCIoRv+&EyG-hoi{YaH|M(wxy}OfvGRXsKMiKFh(Ya)GW~DHm z!5PO2$*IN0?Z}LmI9U{MqVReTq!;;`RS)`i$~w;2Dp*z&_>sOv0PmotjSdm%^_M#a z)JW@*1RqLy;U=p2)!A&|$Ku~Atv0=Cs}9BAv>nPLLA4@g%Wm*lqDEQltwQ2ykvhzF zYqHLLsxn&3xK#L|J^r5+p`**I47J5rwwJ)6^?1++3`LW@{1x`}wEBrQGif!* zVZiCTHtxd4eiU^4@ibV6z)PEW6?UfyEk#F)M70)PubFm zFCiIevj|~dH4Q^o2E?%(7R!^ZW!TQ`uv7RI0~%=CO7J6RXlyz=n1AeS*|^r0rVl+fn(4l8hCnb zUT-LoagTpIz?D3_M@;4&ShC<}!0NzMUH|hpf|uR}LLFG{1rKZ{uzZfhC^+*DQ&F#w z-G=_4H857}H*xL&Hcz24ogq>2`fpxG{4<7*?oS$uU! zNqm zg^7~0J6O z1&YoB!J!BRAmRhS!oXB611eG`DoFa#&p=VmjzGP+(oNBrpg0?Xu*Jku(h5PvOFvzx~XJ;Ub`bFDN)O@HmNptO6 z-MAy+p-S;lQHf9`5uhgEp{VrhOi7~dl7#$A5sy784C2WkrMR2rk2PQvW;odw97(m0 zIk0LTv!Jke(E3Pcg6*hyZ|=0I_uLr`*+W=h3okbb(I>yDn{N@pZ|CLnA%>PlzaN1LYn* zn)7kz;u)07U7cTPj+rvM`V%jba8^|U#Hsa}_)n9apOKfoLdaKqZv}R}_S<2G}m56hV@QYma$Gx9ss!DE$My>VX^R#2ps@J4g7F z2b9e%$3K&MrvECZcTI0%I>^SW>T}-#w&=k=ZDEd-D>yclEV!ILRxU2pv!hSKtDtMB z9#+wEA2$v#Ta z`|8CJj`d86diH2 zy-L22*ksgJT>UG9LHy$H)K=c8--JlBa)}q#sv;K?WS22G8R?uth`n5br>zjyQOODq zbt7gFL$Q3|$GSonrc(J+)PHaP!2LH|p$_ye68fLF)Y<q54)T;W2Rlq_JToXjY{c0mCb z^40v^MSyryWd)goIX&`xC5Q$!Jj`>3iZ@Swg}$7vI5a0T4|XNt1VBGD){@&htG1D6 z6(vSExjCF|)ET-VY%XbWn%)cQgQ)bZ-PiBPGCGqQS8eRTvfiWdb`XZL(6+l)&XszWvDv*XlYJ=l~}9ZfXrLzs>3C>x43y(Pi=>G@qp00 zv|b@LbP^R8p9107o*^ach|HwidaO8qN^j-d@>z;DCb{2kwn{<%hL=>NnqBjNSMN;| zw53D5v_BIw&|nbn=8V3e+CyvkhXos3Rg%_zP zL564jZyMyWTmZwKFibboUuH3C#8|LV3rct9GjCoD1fW4Nh=#2r-ruX}(5@vZ-h0sq zpuyLL1`vjSae9C8HME?SU=**!+n=}TL8_cSC&!YdT0&o~2gP9wjlnw&0|;mxK4MBx z&Z*%I>GLMT+MCrPPNJGaqwG@GreyX?jaaR1&g|Mna}jQxm(K`124{mx9-LW+1{pc4 zvB(IG0SwVS;V%o)ED#9~BM8o$#wcg2!kJde^1S8{r^EidppLu}h@3{$@Mp#6DhM`H z`=nSr39$6m*j~yXyc;;n; zlrVgNBTQORaUtlE5O!9}R|ubqJySP@K`HjYoYao5C~@K;`r^#eWkiUeH`eAusNg7C zo<+m+5``T!dXHeiq2U$t)c{@;I?Gp%Q%Fq@kEL5k-M@m9lc#S+i8ORGlPi#te6$Oe zZZN&Gv%rRKIK9euR4_05Fetstw^*O5gS1`wd%Sa(@R08~+lzHd(mRMJ+W@YC38gnr zs}5eu-We`Qgyy-LHh5AQv>Qn4*1Z=@3;U3em)o8YzOap&z7v*D1$1NZmGalb5WWLo z7*0-Qud+S50YXQfY@g$>bV~ z=ho$qjSS>PX+n~)Lk0tpN_NycWbE3+BNGo(Mh%v;?j|c+?V?&;B1+2XwL}UAvC^Hp z2NPT+hlu8zg?d~zs-xFTtqrVO$~n zL0&l!L(%4j&T=c&Qj*;LWhyC;DLV@J;`|CbG!vG*<4xZCekuFz)$M9I1e-Yp{$!QyQ&U+4$Hs}jX z^*Wm!fT134L2oe(g_+wg9Y1)OMiTrby;w-l?n`=NT0G^Qm7C4V7y1Bbaz{G(ZgOWj zsbo6No!IRq4fK@)`&njijP}M_b~w_G*{^%}BmLq=H4bS#IQr}c*XIK75^Dq=<9$EN z*+RRzniGLdJ#7E!s222BeI{86al{^X`p@C%Z*B2oLnj23L=v&9pg0;aEcOQbWQwf- zJ2+SD%kGwQ#S>ZTTWBGgE%^fqtN_P$87Gd3t8GKAdT)?+HB$=UA5R`oOH}0+sx?)j zTt?J+!s1tI+1-rL6{s*4<6OBu2>9SnI!t~tfusS5KxUVF2O}a^P<2~HWV()7nK+Gt zEaE=O4A2%jAXZjXYK0hl+xG6&9=vrMcCcCXcfUjDj#n+xZ}Pj$+-DkO@A@wa=`*pr zU*kjcy?AfHc03^gPlIV5tAoP?*kmL-DG6O64t{AW@BF;pRdFqJg|^w^Se<8L(T|a; z?*r|h%@4wVU>d_o+k;G7W}zvjKoTbocK5n#e#x88*klUlYWoOAc%Dix`p0u01 zUR^d)#rCP3Z3R;#ceS+PJzt*B`y9G;4W_lLW!w}oA52YsmT+2(S}m&og$P9#kdOp| zkQ$}{mATbPJN$ZxG;>&?Lt+l$)Q)Jps>47@V2tmyLXFD8`Msia3-FrX}>E4xhn-@(S z#q6_sws~H#W~p&_2953S>@fyW_Bk?`@u8+J*Wa%lrxvqir0O0<_h|xy}HF! zdiYQTk=uVK-gKn)o;iy7l_Nr%+#qY>nEVq~1>NpX(I@e~rK`&wl=z|0SD-@yc|eZ} zqgWW3$_a_1STQjllwlt1T5X5lAtrJJFRM}G5wT>DrC9}QG97sp+H&w}==r=)lt$R` zrQU(1RJ8z{MzEYSV7?K5gD^;DzfPYLZzgY6I%`l)R-OpfgXRZkRt1M4j;Fxp`xp8r z`uolG`YW*KO^(;{dzfsjSHtf+(B=0|75y58i*_x$UFH6e3yIwM_3s`&%vYVU`@;L7 z(=bhmb4Rv?L$u<@&O4HlMQV29_B##Teb8Yq?^VmhkfTq zoL>gin`BSv6(%ZHwW)|cPe1?NUjy0mPcmWt`ZdA*>lerWv%i)$Hv*#nl~(5*uQ$!}vgz3K;QeFEW9s$% z)ANb$M{z&p1tCt4M*tCAFL6I`c@#>Fo$|Y0NU`ijWF6U32@&8xv9$J=fC8>iKIBwN zM4a-$*bJS7QF^CRP!R_Jk5NNMg>DT9G1e9bgffVd znlUMuu2?9cB}fpI&!mExE30MBERIM0%J1v^q>IAj5K%iZzfmscRq||fQps%K)502@wX)WH z9L(ZQ&m=1~chyy2|J$R;tD}cz)<`eMnKVl1tx?6FRWOCIPCaL0F8<{E2w+2drI6A}G ze5y@yF&VXjhK`?K6-8V#;zXkJJGWkD8*BHtsbFRi>xJ_h=sN*Qf|EF7K!Ou9O5{+g zn9`X#V||r(3;!_`jo{gsmlQMl8? zcra93PtXmN;h8jSbh((Y5L%+F2H`xGOl_=_m?OCimzN~Y+EI~;lRx4_zT@QH0*4R; zMf7ThFe8e!)bq0_QaW=ypA`K72Jz9g87GcZm3b+lqW2a?MW~Ww)(q7$fDx9CxRDoS z%9xc#b{G+3nrwTT-?JdpSfW{nKHp~EpnQBM<&t1*AGBV$sj#+{D&u^SZpcQUA=3mg zzy5X$=h1W-FuGtbRu)y`5@X-ED^V{@%_Kx$e@&m3*_4HK{=45iaJqEOqyUSF3>U1s zF)44UTS4BD+#-N~o#9oV6Ej@Q6QswjDsoU~tVei8;FBN0&X_cQ;1uvQrd+~w<`LUF zeJj6-q=R!7X_}&FzK93(w3L1)?O;Nh7~%Z%x4?oSU@0_3Yb4_!ekkKuMCYPlD;??2 z(ud!;J!1%Q8>$I5}uln-Rr-P*aa>|Unf@xbUZ={?==30Z5|y6ki8o5 z*v_aJRkpaeFCnS-Q?Twi4y?|?izRdAtZn8k!n%L#628R8Fi@pA=KNAxY*ooF+epQ8 zz9v|_EjbyU3{|~?1`#9UEK4MS0LamHL3_DzZQvpTI7Gw%u!dRiP z`GbP^58Ys4pZ@@8zJm-i(}um9?R*0X^xOih&@0eqz1J^~%?1B==#g>H@9y!L~x^x1Xvq(pH71tYv-o(wqzpfH>zy*XfBy`xa(MK2?~Xp{V`)>5rwehNJ4>(a|$ znx~KsF}6BJ#1p%O?YlI(gs%?EJVjUyicxHEC|@e?Szv9y#yGEy%|enNwaxJWp<0^u zCpGVmPM?Nv4)1b&>Wy$2OTv18#Eddyb}sXqBKP0#+fbzv+^idXb4*~K?=TlvKgWw> z!o*uOOhIfEXnTh;HJT0ulYIh861vb=6xjDQK#_ja9+jZ+im0Rds7(o>(@XLE*rGs5 zOFBfxd%;~hC4Nl4L53QSu+fMnJ1z+}_Ni0c|5iklptpnWzaxmNZ};{^8%BDLwz5G!?`arr<@w;VhVnb+#TLAzh+J^n9;jz@Sj zm3=ae7CAU?NTs!Q;Z*awcInhpn?K33KbTukLB`f0(Y=BetqRT-Ri>4fE{goRoVzL` z#!0}-<#Cp&kV866>VXdy*B!rjP2G{?=Tb`Lp;16bi+BNP{N$oru_O#z)ttOiW5$zY zw9;McGB_!Yg+=P1|8zCSqP9t^59`Lk-D!rnmx+Z;Zbyu348+*dp-OPKMhyZq4?IA_ zyWUNX`R_!tLpIF{6wDjLW#f_PTN@4A7@5^uk=Hn&(xH(iH>JA8DpAX-UB#yHj>c;P zu#)tc=oXRIPQAz;Y$-#d)7WC-%&4N2DZcFH-|Es3t#PU^Jk3cFc# zgV_1&QQdlEvu1O^;We1zdDz%;8Rwb&H3NYeD|{4mD?gTtA+V5iw(-iM+jytdg_QR9p(LvR)1vQ4oD$8l+em4h@V)vXVJ=;J62t@omeSnc?-$t zPZQGRrsqLd3Ma`-&FJh|H92`UdBvCFnnaPGo1C5|xoS*tp60N<4oEL$(0#_z*5Xbu zVSwMC8>C1GS%gVbgX}O2$Gzz=+BVp_$6l6^RB)xl91}iyteLT5d`7@YdKS3Ji>abM z0F2-r@lJrAU~kR89B}q&gdHON@ZJO4s$XuJOi9n^ov#boQ+xLXC)dheT>g7$IrfG2 zf4XZFgc6YDvst+_I09FPn|}&i0lIJZBBU8J6|6)nw}&a#btnfX>l&`>ia0X}dC2;W zC+Z`BT$F|a;-4;L&K8(wgI-|Tfpj9bq*8C|WJOZ1kQ%145SR&{BqNYs= zWlR&w%a~llJq1|5<3v`ylI!!x*2Ml{YB|q+Tg*3_tqvh9O#mF;%?er-ggi-SOCxhS zUd10B^Eu>Kz#(}Ge@rtP7{lsykMao)qN8!La=)qe#+{fG&UHV&J5z}|N6+Xg3(;;5 z(|P%+I7ak+sgbTwq|32Bt(etU$73JqVJ+j?!QCxvzWH$Y9l})L1katid*Gaz1}D!8 zmqnLw_K#ia9+z_&PA?Yqr{NexEQvghW^XF~v#h-1^&(_6?qQ#_k)s24<*wW{ zgrw-%N)~Z-smTWNbJRV&8LRn}haPEt=Pbxx>CsW(hon7S>KbaicTW}cZJrzV8u|<* zZ6m;auM8kVDZmYoKr$8lEWF^+>VF7+q0%1X!DSw|s^q*)CXTQ@91=`&yB9FZ<&;i7 zV7|Cle{@ZI-&+m4{LA?CM{n*OT(Ufj8R7hXf*V{nZ|MrRo`s$sCd(7!Wdh0_DxGx2 z726ud@oIdfuGj(A^B$yCf9l-x?JHCSA9>i6wM08N@wwW@fn*^{MO~-+9zHWQkr4wEGEJGR9UHWad%`_=_HK zgdUE99?3KXSinwb18vQS9@%4UtbgVeN}{fz9Jw-{7-?p`?#njbo_B1WSVj}qO4n1+ z>qP_Y)L-F?7+|9Coufr=)N?TL)-cyN!%eypdMRuo2B|2=X7s2t-5UgBW;-;93WhO#aZFO>a%YsA%zOF(V; z;b6$RY`4$_D*_Wwc#8*|-rh<@KWnm-B+*C||C_}c38zW3XbPa3nbW28!Gw&9q05g+QY2>M-)~RSjzexdn zNzC=|i5WG?=Lff^&pdU0{HEBYY)Q9oybCsdcO92)51ZT;d*n_r0Dt(gC+K6$Ie^ny z)mVH+!ydu9KOcKJ5<;yu);`9<*Pdr?E#k8Q0LnExlp6j%Ka`r`@u%+n3p;Jne_w3Q ziooeP2fvoUK}-AwPw=Ox z@R=U;LoMiwI~d@ zyZh5o)vvP+UW3gZ2RJaP=MUi>2R<{$bcv7M=Oh1L{2!#&ys~`8Iy5qH1B%gzE?_!V zOh=A%C=1uZCy*cdpQnYu3nQ)R}3Mz#plM09A z<{14;%Z5tJhiVnVXXHsfF!p<8gS`TCzNupdTTgRm_L#ZlGCyIJhM^wY(ax;t7+Aex z?{@z@ex;t>@D)Y)2uJ=fRDY2v56+b3{1h1K_7}c#bl<3Lo~bB$!1NB?++lqJ)jsTK zxdH$5Wg70qA`avhqx-Ui-0LVGqK_|PCt?J41IPh$t+@HMmY<_OTf0xFMvOg^*3G-Tkgpzb4B1f5R|)(i`a!MH>J{tJ!PjTCqx-Ua3Awo?QEI z&w7E4UiKHWz4)GBp=qeBix^FN$ih~b7^f70^9Yz9soIly!2~ZyxIi9tk`fvr5u)%9 z4~9ZHBbLbpu%%w*;<+bNy#A@xPVqM?!rVd5km>Sb^zl8h<e7 z)Ci-?Eh%U8(LE|sP1q0SKQ5iAF0S=tf{g{jiRmX_ws!{HD7OH4~rIQRe<4W=^zB%r5hH{uxV-;)y zGEbsq_9m%m?cv7SLXESg%jT?6UhGw~{P(sazBGt6YTu#^lDWi>DH57MG3U*{exscs zr%U^18cZM)@kcjKZggyJbYy+|_KqdXF+#F$OcFnEDyC_*q%)q3XHAutZAyjKI=Cdw+0I7BXRrJVXp8Zt_) zEP-WV469>CODe%7W5OGgx?s)-#URF6Cy#27O+5@cA0FKRt!2znla$;hJ3Y;i>tKW` zpb9x`b2)|?jpvA-ovoY8=90cbPT>Xy+7y5q#+8p(i%cc7KuX^5zJjXR4+q1}Cc zCt5B;Nu{$|hd0StN@wNGwUl*YJXp+I=vl6}}gJ zCOh++3kM8?^T~P-7JAAcsn$f1wl&e+Fvu7k={=4N>l6%)5mh%x@(tem$1o~cs%(@- z`S9=K7ZuD3Q(49w>8+jsWnwq(+ubYQ_EGOJi2Il3m>@mX$%AzI&C3EoOfIbbr_-Ll zj|a_OR}A#Foj9L&|I%~hHY+y}CJf$<71MS(=j2^QFYclV?2JZKMsYidu9%H8y(EsZ z4Jlo2$x>rPvQ`?k&9HHM^slWwl2ActN2XH{;J6$yGA0A#%9j_RVxCebNB+)n@mEC0 z9-=|VB!R@isLe_BmN0pml7M2NMWaxQ9_ zIp-&yHoKkaO;1U7%}B4~GP_VJ!H*y-c$Zn~EDcui<0APF#VkXHTL|gh5W)Zqtm`1} z4dU6j@`r!7{n!_BN_jntIL!svWcj<9B}~V0UjySSZeB{9`{;r481Y0yzHZgW7jrgZR@g1SZ=7a7=Z<@nx{qEy3*j%YtIFu8Wz$6 zgPUrHrC5WV^KH zqb0mh<=bazk}xPvkC3{S(dsM1!ae%!giU!2Pkp!7Kk-ne;&8?+wO5|Rb`RSg2$OVe(BNuU% zp4Qmg7b73>>umjL>&O0vg_EU*z6aX+DYbfW)uDvp(C?;)@`o4FwPCphq)Fmpvzy(L z3h<`&8^s^;=L-4=1&GPxnN`Qm+;8_2;G28H`{F|bN96#;F(KMVDU_oUR;Ln_ugXwS zr5II5NxxhnT+M>4RBgaMRx!X`iTSXmXB9n!Xc>hzI6yu~=SF+?(8aWgU%>9<@qcxX zT?mGXZ`c`~8+&wis8VyAI9}`CVJ}^_)-Cex?mR||E7~p-?vWcVLep6R4TQS^^G}Z(j+(# zPhnPAJM1vTMc$U8)}=B_6ogTee{H6smX>qWQ|0N(-|3y9bueqRlRVkZGlkpEluwo^ z-gu|^^6l~?5Np6w4O|UF+A+^H%ylEzQv-+UXuxOx3I|vVTv=)3h0|>jL#kt8lBj}o ziXgor2)qP}pzp{al35feQ!Be!B){I62~Od;a_<2xQApyH258|LyDm+5F)eGx-6+GR zR=DLF4l@nNnWiL{<`)eU-GEdztm+!r2rcwOA8TZ#HBqt4D~)rLCqah*AB5*e!G&pX zL3(_UOn9GNNsH#Ql5Ae`oomy;SvxcdMhlbXfzDgI>Wp1nub|&Ce4VZC6la!z*ou2_ z3u2mx?!TB7URuC4NkFpR2sh$mI@{X#giPs016?>LYp8lB5?FZl#5}uV3^p7+u?+5) ze9PWDAPG)rRCAo#oL<8x=WOiQt4Xk8bE~z3Q3CsiwG@i3nbn4TI^(&w%P(PkS z^7kq@iFZ8)c*9y@`L38@p4y9tx`2yoxEaT~u#szTD%#x)qFm|Yn)$@-KY50~gxvX9CW5TA>xT& zps{BWSvAzUoaw!|DKv!&jQE2}3`A4=ZN7;+27=tM@CB#9zf;f@s>dx<6`9=FnP>&e zm;WFw0S)$71&MBj0oUo(j%WNUX={8Tk-fEqY3~bjTw}Iqc`Y9O;F4?06U}~+rD^C3 zHC=1(osk#gZ6rQ*lcHGQe9NxXo%US%=4S4Q=X9X^`J;o?syKg#;jSrg|1-Y=H9aG` z1Ph`Pk@XLKa4KBiz6UXaVS!!YO#Tezb}oQq!Gpp)Y+Cffr(=$Y_D>Z&B?*=hZ6I<% zk3uB?o`(a8_y8PxWZHQQZ~4k!(C`y8_6&U)ptqptH{rdfE-O-xT&&lG{|b8LV;av2~1 z01Z$80MY;RB+A)^|CVZb!)bx#9DHTHl%+NK8u1R3xoet9CM!5biWKg&GxFd{OtMbb^ENO-_QRO z&;T@ERcD|lsGEu?Ltao+PYkpZ1(jy%J5MJKg@#(g&_Fk=rqSF@w)Y5Hy8a>Tu7fme zq^luR-z?%3nl(&g)Y2)eh0x}wYPrt&Z>(l}hm9LnnJTj`;oY#w%pNM<@Oqdnci#o{ zI9tdWvxVx`sof|OZ@jYau)}uRt{YsaX=WG70jo~q-4(d4H2RING?=U1W?tXZQbNS` zp2!j=Yqo6IL+(w%Q_YORBz)*REP>SHevHJt7-%B#(3x#zr4|M*8oFCDenK17?Bt1U zIW;di%Z04Qw%vR8;C4lg9XD?KpgsgA8m)_?r+>`3`UsygUC_h+2F1T* z-T|a*YGNt(O$m591LS+=P%0k1kiGz|pPuZkTWCDsHoyMI(&?}87m5WYUR}iR-@yGuMCZnsf|EeHOvGFEIE^d8PTB< z+hVnN%SY$)7U95TJr{-~Y95$V@g zH(XE3eEP$I6T2UL|J@k%J-A#?(!4t7eYhP)6#D&v6}jH<8L!;-G=2Tau&Z28Ui;1f z`@j3e$ahEX{YS!m?S{OW^>>EU(-|?_A8%}98m1%pPsiK4@5w#FvF}E@-(KzbzEaY6 z4@T_BcaKKC?K;r>Pe;5lhkaoR!qIW}dBNW={rp}5^l=YM;UA;JHPGNW9t_br9uUF# zF2hti!qNH0pz)8Y^PdhJ`M!eS`;XDX-!CEgzNSLu50!mhtoe9m?eh(X@?7_w;l5(A z)sCLN?%TgUK>4=s27Zs8?sDF|$@?bge+T~h9}nlh-6P@axgAo&`K-e7q1D0b9}Qpm zyfOFt1;hIv3}^eiRU_{?9d60_gdcpz;(zDD|L$+O@4Vsdo{acECcEdp@#X)XjKIHr z6(aK=K8?$LvFHB|hs)=@QRed-fBaqz%9>SGRkUEVp@Et!)`|NUTQ$oE-67o+TRTJ^WU=WE#8I@z4AQa;o!3cTT zGGIh~6a^|cXc8caGF%1=`ghdLqDQ_FLu4ZQbL?Al58}ryB(=UgAv!<`Y3Wj6M1BM< zBKz3p`fU~Cf4#m#>wow#1$~>~1D3?LP758ZO}#E$1h%p1pRny&_DLvnEFjiyFYc;g zTHIM2MbrA}GbnZXy)%vRwy{$(N2XQKZ(qjOtvAi?iIm{xBS|=`^YW5OT#%Kd9w>zK z<0anxuX(}0IW0MF$o)=K?Cp7CD0&^Nj z&|ld66V1P4vAy)4OC~KeOQMJ`iF&6x+{?u}poERov=XsZOWOc?s6|jQs=>s8M(SO) z?LDYAwX8(8OnazL&5ZHKO_l`*qKzpN1gwyV)TRX%_*q@P;DYm}ec8<`aNlMV%fcG& zGZ;b`XfRH0T82kFIcz`ftvGfGOk#?>WXvgu)HigM;qx`2XmG<&b5micv#;0IkYfdp z-63R>^aWWNHFT~oG@;cmRwo_8&Q7Xf3=cFgmhal!U915#X!ZveqBGE71t0EXQ|)t0 zxcog6m|5&xgxm27;*)z*0>Gq=^riA)Xe%7#dn*$Fxr`T~L}3^(;+S+8UOII|or$rM zagoYx-tQp`rpb9WCu4@d2Bi;UC&L&(;K8_>UdUzqXuM@bW}+n_mW0{MiYYCtdK^f3 z9sk0HxGB-#LJ(4dcoTsPC!4}To9kVQUJng6DE;{MuEdpzIKd~ggVKd>wnyHaU1Frm zfdNUTOfvROFvC&ii=5p1OI^_j6o3u5Y1)F#-e-mPsJmv&OFi(n_DfdM7&Zf|LW zsx}%oS44{_*wX=1T%8x;r9D|+38XeQ>DTtc}CnxFHsTCRAdPvp;WDx-} z#$cf=Ok-QbLQW8Dtu2!>To#c85r-W^1*OCX7x%}&8TSk;#B&luHWeqGo^CWvkaLj0 z3Zy+W#Z-}r0;7#g8ERQ74JHn(vwv5H&crBX#Swc_n2(Kia#h9L)U`wopq{Yaa0Z%<_ zA^1%fZD%zUBF!IM^;!`#R^l-SH0y(>%%z98t6+A|Zmf>Yzk#(Yb)6W(Is>b}m5Fxg zb9Z$Nw06p>GDEFq+YR)H(a>jd@q(|?>>Ah5Upjz>a(t6_Z*S!kdfF>2mOuj0lX8_Q zh5*IxZ!4(W-)2;|u;E68o4AGD^;kg!U&GxF_?5&-yERQH!eP!ywY z!{!k2BG69$B2r8<64?k>S5oOdK;#HN=1MNr7Ga9l@!nYG!KRKW=OoLRX<;q1x{NHK z)d! z*RbpopUdR51~Y~7wd|Rmd+MiM9yM^c34Fjz3qC~5dwQ2wIs|P5+!kh z_5Hm*199%hyn7H<97KlcdXxRvL_iIlta^_3~f{x$*%eHJTBE%PI^u<~a2i8%R2!}EDK?x8d_QR>*SG;g?Od~Ad43YDwcJLzYXx~8v2XpTVW+j}LRB0GF@|wtY?-f}#Ua;OU0#0Q~`aSVrX)jPoFM%Dj<`;Jx8!IL2v& z<^#|03}XY>9?Js!Cs;=GGY6=1lRr+bW2O4a(kQK9n3|3(Dl@u;5=Yu*pW)WbGON46JMzIzw2#N_38y@adMyKa!><`s2l$EI$=_JRPYp zz<5Ql6~(g%eNyFX-fMd81|sRJ(Xk`ACGlEjJ~>N?DgU>pezL z#9SmH9^@HB0H;@mz)urF4jfwsglG?h_=af0aeqZAmD4ub*_lSX+Hzn^DBr5rEes%u zw}sq7QDgd%Y$2X7uM~S_rY5dr7<#wzQwnG9fJbd?l~5bkN%~CpS==(LxCTBsrU~Up z=1tDkf|HmWmp#21UUI?aP8Af9xA-u+nH$nlTRYHWM)1f@J)RnH49h~wy^2!=R}%G) zgmB8XsTxhCFxQCQRuIS!CiD&lztoH(l1I&i-$u}Y(;JcJjct6ps#13DS#{zRY=x4F zuLK1w7#u*G>5YYi^i!Dr{)0AL$H-^E)8k1vq8VTe%(`=B-F^XgtR1w;_MJ5V%^AfOQa+0J&H~(c_QSUjzynSlKEeP7ZqH{*(J$gAFp;9VMjWJ<%k8z{UWl`4{aDP$|+{Y zmk+yEEaZVAA#0>xgte8TKB!Y?N~^hp7X`fcE>x5FCaiv#KlzR{g*g`Hh$(*8aF zeIF&m7g1h6iynawk)YJJ`WxxzDCHFIVVro@>Cg;`1zO*;>Fe$v&$3>Imsw5NTChJGFaAG zI*Q8AsCLW1iLa4*6D@O&0e%S%GIJttH|6o0pdFe^EKXQP(8`k0s-5sD8f z{a_=B;BLT!@&aMJ>+t-=mtFvZeZCKF0PvHS@B08A{2=g)o`@g3pm56*VwY7AtX@Ej z3tHM<^m_mZ`dx4=e3v`I23rn**UtgRc#wMvT<1ZtapeI}av`o9kc|Z};sRW}Lb@HU6 zUUZyyFL;;>z+&hh>FK4{0UNEfHS0_@)9J>OtCkM%rN4s?&e*t4HoOUf-tHR>R}>djL%Z9+#F!F|S~^;O2x6*NGehTA+VoL3oUcCGF^5KyjkM#tz{Xw%G?9bH zp6R*gKgK$gdt{2hE@Tv@;FKpW7|`ZIl)bqyX9BP}(9s7x8c=7$R_m}=2SQ6fq6mS~ z2I#r;VbT|SfA^_6fb0UOC%x*z&i1k1fUiT<54_%h>_lK+3$g76aXMhf2X8cl&paK< zRs6tV0u@bU8{!l;la6a^Fe|rX9%;z5r>K(elU`$ksNUnQ-rnOfIlL~F$MkU5@<1AIil+v z9+@PeE#ejJLE}wP4O*V?`${7zBb{#3=>A~jJ&F6dbkGgbfM9si)DHECkk@* zmTVTPUU7O2@iuvgC+AcCE=|Mz>FJqjng#Z!s;6@#(0i|Gf1yZGNvs0=5d!Z7$-bZ; z4}>w~&zRoWB~O(zz<)zgUG$*!hr~FDGBae6X3J7-c)4Z*gj`c0r6X2@l`6Ao(AYI; z?2^_dn!JXMUQtJ{!A7sMQZi(7Rb7ITXLyj83GkT>cygx~fX5FMGNL;ha^|cV@Yjq5 zk<`k`8@m1-nFo(vf<>>wMyZDM4`fHJI&nR5&oVRG<+@$S9+5B&`_v8)exdFvY4?}% zP^ZiAOG{3jkSag9-Gwi4uw0mU@L*`b;^pM-n{=Wj{^z=9>mi1Hw7+)`wJdjPQrxUr z!lSUhPs0O%%0H?LccIUveic5cHCQ%B-QD2EK0rcP2Y}N76z#wgJJgEYwgzfWh$m9^ zPFH}0O1m56zqlp<_tgi(B5D3Ckf)ejgR%>Q8Eq841Jdnoj=%PS)G^bJXriTSrlsQ# ziI=(eAWa-q`)jj-oI*pUI3vOAoVUa5$w|CyUwEd>5qZC($B|wm%?+c-brD{eE6>ZY z>Z}7Vvjt7=czqy__eZe8%79ar`~bHf9LC;q12AI|6jU#E3EVtescFZmp6t%spbWB7 z43Gz+nZgsP%7^W0Ls#J_p8D*Fo>ljZ<{=rf#yF-8*ul&~W=%Ap)a ztoeWl4>sB%oyEvb10a3KtOp{v;nst{@iHwzSI}t_P;Wecn5lygBJ((T?p`d zGY<&+!0|@tyuq!~WAtPwZUSl3EU_p+{N+@!jcHlNV_mOTgwE;YN6hhqjIcb_vH|s9 z#m-~oD3&rnmFf(ubg=b5`mf|5%H5!ga$(PPE=}_kR+1cAxCiF#{4MyWYF8&pJFq3U zj~QLq=T&JY+CLO4YFk|eDXI@3CeuDkz)u|#1>?fTTx|KOs#__FW=+^h&sSBGT)NLT zeAb$4GVrHYIxHKjQ`M!zYRa^PdvMd`)S9w1_h`q;wT#WsawqO8VxVubTCL1`lHB$I zv0q+>snKp6vbs-buAIvCPG=n_Q@#w8dwKTrjyJb~qVID!?K%w}J9Ow?&`#UgtHrR_Xt5L6{WH)eS znHKqy(zuRAxM+)WIORG+l05|Dot%4#M=B$nksa)sSu$JC9h&^m%95$@NC5IQrOgHlTd|xp#pU!Wfet`1_>G$M3K=#lf^dSMnLc=aRLBgTH;gN(KN*L#; z7aDXt9I`N@p+xA|B6xM^?;WBj`)rIr@~ER7$}wZQMlgDGV+XEAK)Zrx-XfH{)KvF? zjG9=Cnh2yiu{o#CP?F6x)#?;m4t0*oldVZm{pFQv9q@8xEMFX?SJ4-HzZ0c64q&W! z;^$Lw>IyO^xNEh!OGMx5>=P!p)t1OqjUOA+8D-z8OlP_;auQ+pEntEhX_5lF_kL%)nq@Gy#a zL8{YS2Q|t9=p}hd;qQVAOIOBfb`?AT)@l-oJlP3#ykC{Xl*K&xF1Q}mboz=X*#vVS*&NYIBAW@dbA)wr#hLi< zqb@c)90NyH*;wbw+H@6699abujf+KCMKmi7UjU?4wJ^pMFBn|0YR>5#oC~-htUn(; zJ%#cx%qpETl*;$@Ln#K%s<>QA*t#cJiVSy&;QmmV<~K+mB{kKP>Po-*@R~$o6U5hv zM`YKe5kb1b|LTY)J~7prfwH7e@s#c!C3f^t4v?ch2&S4QaL7a*0?(}5o$~b|QWg)qx>f3XPV5p!Mxef2sL(v9(e-L2C;c9J z{87eTP91DMm`eEp1641B3SEZ~jiQQP!PP?)NY(tL?2_u;S^5-r9hjU!XLq$LRRLCt zY-K5;4t8v*nUca(AcJkSm{JIn#97}!qAGa%!c1AYm_#PKgra=?F9F=et{6blaJr$?Ec!{%U6ZnU z8DII_3j#@3hy$|;V`N0;(V|(h#%W^L%Al1ke#(YVW(|GdVT(Akd}+v;`)8pGb`$E} zn%XeC4U0&NI7jsCsnvB&!iH=#)F`P7m`qs>lN4NMTzL&=_K2P-Xp%!rjmNWPiN%n; zMuBWwjw?2E!H!gnJSWt+(o+0hd52Ta$_9Hd+rTQ#pEj*(tM&QLEqgMnErFFa8Aog4 zrY!*nDA=Jp@?2F#SJry{hRmv&W*84q-ko=$3q0q8rfQ%xus?6%dK#o&RKOxvWX;WL z!5vA{d;sD`219h7%;HP~ks5ocQALbKH`UqZ6`58$r$VT*pu`>yIKW>ytLl90mA)%F zVoX}XB^@a?J@K55aM9Nvp{N=|rDAW>zT(d-lHngjLw12gH)6;eE{Z>|zO@Sama2Z= zqtOEG=GsXfj^Le}x+wIwl4$gAi9AegD3o6aHEp~hltt684k0-BpDwrQF(@ae_$vEZCH z>{X4+G76=8$oO)}A-0PBDK5O209eTG=Jq{R98$a-%f;r6&L|@41~D!jX>dgj?;xv33BR&o_W}8cz9y zD;P87j)~soud9%l9y~02j48B6V%!srTv1}wuWT6L%`^DM`PpvLReR~H3C&dR@>Og7 z)m*3Mz3@7o4-)Foh1&Rl#4d{?R~ttzJ&as|8o3fRUXZGdBUh*NYUWxray?^e=6Ir3 zG1c_+iC<=!=dv`|js2XfBnh^L(<<@dh3d(gtO=y^lNHj&PIH4cWB;l&s~E%PpjQhd zROeVgx$Cs(8kl{(c5@o*dV}X$2k|z1hjbl|;BE0Wn87FefMV$xAK&0Pb$y za`r-MKu27chPXbF99+|+eFGzn_o)?=WoQ`0-Jg*VTaHj%um{%lV@$E)4`lq(T_|)HcJbktQMm{1`~rMz^H;d{ z2Y{y7y}EKC26W~kA^7RU!iwkQR3pt!rRTf>3B4lB=3sz!FLNiaIf>$gQfX?LqDVkCysF>K|b>#;2~&sjIjTI^(cS|D~tDlp{aTVORJA7~jH1cf?SQ_`@dO z{3Q?ahIv2wOCM(qD!)K#7r)Iywq%WyxLELj;zqo5gkoe0L9F?-pxkt%-KN#Hts;w1 zchb1ENqg;nWTK5W`-H>qJ9)a|Tfwt{a@o*4Z7ub9O!x8!wLzlkC@*vxVoI$I-CNFr zNGKa2MBq)f?~~AIt3_i_XtG4s7!6!q44h4lAvQpS)HmRoHYlj|acVHv(t8)LIw>H3 zScX`0P1v0Q^tB?ZQNm=Qgad~X5QiNYN0H`9V~XV)nrR70q75o+DPh`a2&oE0 zEX)E{JIn|~_Dn_6$%I?d5Ne4? zz6qjc+t#$dPvA@;cS~fI+j1GQ=1AL^X^|z%F;Jn~ z^{Oec3bTlge_bjnI`l{rF+(mty*bGA8V>-z2;?O6dbGQn!0WWgEj^=;ABOGHW>y`G zO#CgkVBxkx6AZf{9&OVHB(~fm8=?z_+&E=gzXzsZhzCQlO@Gr&VH21QXzYgUC9U%e zPr8vGNUnyP-nFZXM)1)kv5@=>R?K5;wz3Q2iKOvGJ({RG*|hilE3_i1NP|42Fmzpj zJEoa-cpYZBoWn#meBx2S%EQv9H82*cvm5?}eH^JfmC!HF+$frMAWL2NH(r&cLF}Mn z8haE>71c^9oP|PBz_?rHrQS_1rvvU^Po4~fWQk}FY#W)T%Be0uTQyI0xQ1&mj%y5x zn_gxzYTK8FK~J~6*yd~Bp%*#yT#!$GG$EDyjGQOb>Ec`BKe0J|_BR%&A$iwql<3#t zf*W`tGu!lq<8CmMrkwX%dF7Qn0jq5KgSEDz70f@0YZ`h%__nAQOuSLG&iiIx%Tm?R zl_(A8T&g70WKSUwg3`W%)@#6!ZLJsx-~8*SC~?$;r^iNC;$cS~c6*y#dHm>2@Pn+` z7fxKaCGi5Tu%|jQdk7s{G|il3q3v44vLRmvJsc40?~>hrpqFg%g$i%@70f}?o77s18hANsD4@(q%8JP_j+a{n0anX#3c_!=zes{zlT&mxr1v0c6z;p7l zy9Q3*6!{7`61Z(l@!$S>d%r#w~@#-!I-*{m#*n3+Ta6`yt`7D zy;-|45^NFmZHJXhv}H%xJjQLJ8guJR_~Qg!5DYC>Btj`Nw%-53cvKO2#w!i4Jcj=j z5(}d1nr@|BbNr<&FNR55%lG-y5(Nc*Q;-+VG?@#TnVM%PN3C6$Mt zemAfu%Wz4KjM!+T4)O%T7@Y&$4BqPE)fG3F=N{$%#2_-&NqPl%VA-x4pi{;qQx0^M zY}i>pYZrKh3Q~u>c%6hKq**p1Qf3VN(r-pNW|t)4LAPV^hd6k~3&H0v^2;A;)}NQ< zWr+1B>O@~UzZG{G45+E$FY2f-H?Nx)X|vrsT;%IHB%hgshAI~gRW2H;j2SRs z&kVzZeVZs&CP{r;wsS>c@|#FCK|V^=2=w@i|G)99?Tb6i!+&Vj4cz~ocabx+HT`cM zOMS~3*%am1Hpy+-G&@WHS}CNBAxYX605DOglolPj&;a^E6p?-MkBg(TVKe1Pk;ia1 zJr`H-5ooUCeIU3C2?LYyIC|zoyc5sfZIf&=ZRrc)-iwak+235}q_3wte1D+zKzS0E zeHCOMk4$)CBC&4{+QrA1h!T*+E*xY=I>9D3WS@+be@-CVAm9_rk|_9{k;XudEQ9M<4GvduXC4pdiw+>ZmjmFGyq80H*{vwJ0Co>0rfMW~hAMj%PPiN; z1w4>LJCWvPamK@S19=To`=ZP}XhHoUmF+p0D9LmelMP!CUFyQn${^dd3>~A54l2}P zU9VZ3zVTXW2I5LfBFWY?yGPetGE;?6^U>)XNsXte)TzI+sxu5j-x#WLqQhpEF$UZD zhz%MgJTb1~VI?*2#q9-lnR8i65`#A7osFyD@iqMn_3r41!F!(c0NXMNX_Os!Jt2cy zbxP5Wgg(y#XDG3xskZq3HzhOnJi52ZLWQ-WWa@gT37BSk)X0)RCqE!w-f%1JDQd(d0Lof$COUo6 z*vPFq1P%EvqfTj4BS4-Xao;q&L4yfLz4CID#n%}or4ougG`*-uLr-FK5mn(JD6i|- zs+#)i_n1gKR;p2=S52UOnqAr#+TBaW+vA?GeQ*=oX@o8XHCD^Bdb(Sb?BY*iJf8sZ zS~0S2L7qG}eA`m^M`|bB7PBj~bKC|qD`u9qg=lOfOZ&22kei+#RRUYqb({cjzw0r)ty#2XsD?{GA7r75 z13av|1vLg;mMkmal6#)lO(@@z{X)${sKpH0yUHYft09Z#lI!(%Dw|;sz)u@(s7Z&) zxpiSUft(KTU!7-nmhahiBwO{_hlOmbVmW~^$QI*_B3{jty5-2OWs=nHVl>O{qm{>G zFsFk`QC_R8L|VXcnRV3-?P{LeDxAXfO7%4RKNR_{s(b=6+Ee0^S$nNcC)lbpZ?{5u z=41wa-cfp-v8~V5Ub`06#w@2%6`g2{E!0Kmx`?cQ2(0QvQ;0=8g;X2_N%jdoY>S88 zm_j^&ctnE#vgwOZLu}VIY83fngPnZItWJmHWDrWN3o>^JbJ%R*HQTmpw*mJnYN{gi z#IHKHB`@S+k*iNksxrCNPDyqjmFze=g{(K^=#cQ%VK(Nptjl%X8PDd3rg-36(}wS$ zwz$oA+Yo07>faI78N>38lKF^@K6m?^RTF>c)FyRsl|HImDbgg?Dx-EAA52- zLtw}}eg9tXS>EUEe>5}mywkHh4;#JVAqdQ-GqUQ7dUbwTQtHd|N}`CmM`+yVT6VhW zQEKhcb?%F>l|!=ZmoCV|*{)rohVE4h7ixGe+1am)H#$3sQtnH-GS{~%mxbS7F97O) z9bD_P;g)>uy7J)|KLFI>om?}j^POK1=6yL*@e0K|T}e{$ipM*>f)@21t|aUHE{gO^ zqkO!gs>^kst$)5?>ffdS{gXEB1wMv$ma+zGL7A{C~<<=_2 z%6)RtE>%jFQF5VNvPza&a;IFfYL|iZe&Ol77Dee9&HZIiwa-n_zbRGUE>O*$=6Me3 zx4lw7^^RnF=4#nH?qt!wQxEn!yrSDb*xGjwE_Lg6k1l=de&$xeb-sg39|+s|4lj-C z_zwE~ov!q0M*W?y_;tS1;cu1ge8*PLDoXaFI+C{ka@$$zaCSI3r4FS=Q|D5%t5@p4 z9!>3Aaj0ABlsca{PR6J>MoLah*CMXR<4mfO{WW!DjjCQWP&0G3hEeC#i9NBx$w=+& z!jU(63qysCjZR-xW4E=f(h?flY8dWc*2j7b-;%;^zky&GM@w1|8nh)jWfLi~Exk!( z4k}FOPYHKr6A#91T++QMTr%($kHFpn`f)I)j9>$4UoD1j4tEzJZj`vD#trOB=#K@l zB}!D=Yii|0x{VR-&N5D<;JRXL$nyR=Sm*Mupe{IwLX32Yd2Vlc`??97gY$2`Od|vI z7Z)ekR_f)&usYC-4H@ih)L`kTr7jcW5?I~+Gnp%g#8r=pXT!tW!vxi|m~l8@ zEH@N>2_Z+)0Bsa!2>eAmtOLEbb`J?=lix$K{e}V+vSqZ@X&geir%&aka!Z>j0i+ejjo37isg$!$HXdlOjUuPsr_4CfAz zUmW;4F(-guJ58Ec)#nmYllO4C;RZI-+_3Twc!BAKbyJjOC@<#TWoBe-nCD8C$s7af zUg0CpevA}d69^x+-DV|SM7@a0N-oQ)86oQM>IE*(w7xz5Tv?yueLu~z4O|a<$Pq7hMgjrB-KWV`a0|(d=&R3lov@WWb40O?fl z83xo>|7;UziG&ZiL7aBT<;ODFzH}LB1Lu~^VIe7-S*6K7mRl!5QU)I<1BtN);_+)Y zKny2C<2wljwfWZgauaeT7ox~4mAg8>l=hs2RN%{Ez*iKLCP0Y*{ka1Is67Z=?h0Cv z(lMAnFIO(~JL9vD4~PVU@*?x|;1nmZRpcjDm0O zRI)fxq)Tb7G;nUp%=@8B6;Vza{sxNUKB9oP)q>A9A1f&4X-Yy^*$?~nag{ZD?4s$xJPRR=N>G<0vJIkNtwM0BAbGhwU=2$-Gax|x7i^N7S>T=R? z?1nB!MBRBcW|!P)^A_V*hqb%xv`A9*l9EjEM9kKXce5e)a}Rg%GbjQx>J3@%d4b#XW=8Z$PiM4ODmi02K+D zX7<^*`5GW=_duBAdVOBgMvfs3z8%?R+-(HSPRfWSxw->urv_rQMZBPfX>*ayLi(B% zr^p(p=C3|6V=f`nn6K$NvA2<#(`W3Ra3?yZSnOyiLk@$ycqNGXGUxZ_MdORxJ?pDP z1UPp;4wJjgDGL#otP5!N=BM;$&Y1J3gC&{U#eCrzqy?tPT8#M4!=-`BgF)46ZQ-tP z^f^i3T0?P-F++|_K-9@p{aWK-b$}!}T)k4Jd5lZf-8;Z|e--fjrwUo4$Zy~YrpnW&WrI~xHJQuYnFR`ZP*UF4 zOt=8mD-C~r86jeYGsHgBMuplmcpeb>t}j zksu6a?OYm8@H8iaT_q{vgD?_Na(D@4guhmBT_~J?Gi-ScfZ>dVIVzj+8G|k~mc|?5 zZ=GKLzc-7QY+$2PV{*=zd4NC%&H6&;kJxr@`32d^aCuaB;R>6@?P z!!_?V$s;U>z>eiq)UilPj_K5tV-zuetRk#KUB`UPl4-wylqF|mbZ7Nas8BGAUlrBn z>IkRUUCp^Lcqwe8;?JwU9m+t304kXU-k6bV>X{9zNdP@~OZingRp9d2VUkD~Z5l~f zK8=)4!+H$Ext!2^Y?Gd2JkjZtM|d`!4C9nI7enhX$s|mN@~6Y3laP9Z6|9qTH6hh0 zQE+&I!GhO!tKcBTY$7>RB9#z*+DdqhLCJc83uu(osgm&O>}+Qy9M=At8|@X1x8rb6J(uejhQ#SYYA5q!bKhw zI6|r6Og&lYi2T7kjfF2HWw1*&_xG@2+Z61WEjgF4otl1=3FQgn1rGFhez zHZujB1wzh+;w<^v0AkUZi-p<6T5&utvD{Ry&Jo# z!dTz3ylwhnrq)ed)l-^3MfOGlLwB$*yj4ENq5fdB=EZ>d(QvEH_yJiC3A8Px{9e{M z&`jK}2U}3Lp}lWhYgX4@TP`_j(g?H_+n)7UYWaN|z+q)BNd{wQ%8-)bxZ~9o*Ed>P z>mF(8!#Xtpj@6GM5=0$aD8X0#&N$xIxjGy+8z@|p%DXNZCsw^pmt?NTVg{@{5~Mk? z4%5)w3dy8wo%K$0C5P;tVek|R2tTu(qR5*QsO@PQ`|IP(5ys5A(Bf=rC*0)2t<9;s zz6%eo85E4_IQ>CS7RZYjD+lNP#09?V*Z-rbf9>xFX2=--bEbfmFQ{s6U&V$~sb&NL zcY!^QeprBpO(H#cyZwNtk2Eht4esj521~m5_^c16SLoTzuZ7CI+-|iWxLn|lpn9_~ z$E@j8|2Q}$c9FE?pnPhf& zvO}q?4tTP><*p(Ld2#Y3Ow@xlQR172Y3BQW%w!w^q9rV+th}}KV8S}?=ivDIt0>V+ zPCvoC9G>E{-$h4vWs{98zrjmKn3G0gWbwRp!l)1gQX?31x35pcxx06Ft{m6Lc&-uH zLovZavY*uW4$L=NwlB5)_Kkbr0sHm?cYyxouszT(JM3LxpMF?=fG<33Kl=M%wlBW@ zzgzdh1NaRG@Id@F!~SqzgxEg}_u@8h#RKu{_u~QlcEkAqKhW4eB=`E8_xgbTQ(^qD zUw_!XF!%c#5BfoWYGD20-k#XL+z0&ahxGw|z_EXb?$d4F@B{m8hJQi6P_ci^_x&3W z>Vf=c!}{UAV6lJ5?)x|I`vLu@!}?*raIt^r?*H1neGdHE4f6y1z+?Xq-pAX#jSuiQ z9{hs*&}0AD@BjW=g8o?I_n>8cWWMG2XN2{)3L#&XtA~p63Q_OU93o`SEi&b^VdExyNbVTdr$s+hKO8zFvqB%&(qB>}aHq-t_ zT_6M+O`~D6NMCpXm9_)}YQ97RYOei!s&O?_>IpU1exF?9OVjYGYxdB(uxZYzs?ne{ zD7yBRTq!j;s#0qJyGo@|{wn_EQgL6ZQoqjxP1n9=TYwq>=ZCJupP>!uH%qJ+v3#iP zjEaVOi%$88B%WOqcdg`FqIsGylGtT|T08a^MoU;0tq^p;Go`sfyyGLeb4qM1li;YN zwFPc3a?RMEER(FEy5+oJfgKO!Huh7r%3UL#p&&5Koudjbu}!~(f5AS~+J^d=RBd7y zlChZB64P6JM{K{ zl4TQSnNBpUBdyP*R&lCZX{bY*;}iNwPjrC+Tmyvp9A(o;whu$P6aWns7qJf5NCX&} zlIj+b*q2m1r2RZ#BIk}`#wiC@(tJlpV~JR7Cr865ChNnwa9F|Hu%OwXV0?%|9x=Y! z^bCUBf!(&09$K%1qOq9hahYvY1+jK$m*mu3nYlF}7Y0h9dUO|XpKjo>4_nMT&qMJ+FS0il z)tF|tTqvGBSbo>u(+K?}Qa6R%O)+C#6x+7l&5@Vlp3V%XHJVAh?I;4H@b!RZ#wl+W zC%(6rVGEF>?$4_%$UG38KsYo8;4(i}89(}|AJ&WypNw~<2l=3DorJ0mx92EGJu_0z zT!Y66+Epr8)Dg-bI0syriZMKC)~NV$EMB5Ng(}89N2h)`{t+L<5+}wJAIK9=`bJ1N z!zdWPLJyWoxRi1ZIyw6t9E3ZJX)cj&3zca3e*w;V)nc6UI<-wkI%lYzU7{C{bj)uJ zZ^?NO?(#KG19(4El%$eLzEL9Mu)Lzw*hT1pedcE%4*vjq#NmtY~SlSKxGPfob z2qQRj75@M|ArORp=}#_+U58@Pzl^jbDhcp)wx+O`6=HaMh363t zq$yJKzJ4DQCixi^FDl@PdSJs;v5iiKDf&h{;7pX7=2AH+Ae5WCh-$^9vChVy-?7|= z_~l$b!c?B6(1XA;^NpU4|Ncg~Thn__bE}zU#(V?W@!*q(!s6|I6z1{mnPmpvR{wRo zM(uaSJAR4@@-?snP{eELJH?E<(e2~Lq<{1v1Kx%6KGi#arF-&t2(Y7Y1Ym`=AQs;X z(V*j$LF}uui-e<9(i3nzAP_}5LP?=ZRkm)OV!|?E?m*>|qrz@$pFf_VZa=lV#m^p! z9U9$^^Ub2L?A)up^C-`|H)rZmI%-WuqNYq`CSyU($1-hdmEw?wDqZScJw^{LVRtR_ z$)jO;b+huxvtgxrSozTPL3f^a=^?(oMgn%Y@R=KwA#;d!NcrI5tyK$`77U>y7dI}g zqryT~au7u$<&wan!kTxA`Le)epI1I{{M&a-_~HV@O5ECK6T?FHZSFiu^7CC1C8`<* zH}Go}{TD)+kc&Zzr?d(;ItNax&d}uDefZ>mVTE6|~x2)xP% ze7;2T?x^z3lI)?oML~B}`ryHD?B3VhdpOR&Y1Q(yJpQ9IjYi!7-RGbc(A|mocB3(WBcSdm>YYtzw;E%F?4163b*BA)GFR95{AhI9$LF z$vQ`HNTf#U&&3TfJEy-f|JCpo=#*SI4uA3!dUgh_E}^zy))l2~O5Hdwt^1=sc=Q!r zQ)+eQ+L3Zoe0fHAQKFxBs_qQJE6u)8>5S|n(K=?>p*oYlY0P<@*zDZ-G>_}ZyG_YH zulr!#p{*yv>&Skcs=oNk17w@{Hs9;`&^gyT;U;xCpm9Q zR5L2jOQvl#i_$@D7!!e~#D5gAE+eof$dPXXUa>}?9qkw`sZ;Sr+~YTBOI(hq2PEhv z@(OvCyoNqgt%km#4`u9~cclsgjt>FHyhWWE~(Cq<1 z>AS0VvDsruE0a7WU23(z6nTm8ijk^|R<$N=01RtI}Y1GEL@&AI2V&gM(BO(#+|$-p6NEFyH8&!Ad7rb#E9 zG_jNUlpZ47&A&a6>W-EevEFYOqDR-NT#}yAX2A8HE^r67^P^O8*1Rbv4H^19da$ii5_D@I*Av z@f=`18e}M*PR$&0Tj@&54A5QGPW}Q_;tDX92!B<5qkeM;##efq4@T2eN2UvMEy#*# z813*4Q;5yui3yww(i3_AeY8JN4AAAAOI%dAP-M&NJ07z|NrQSfy94=0VgR+Ycf;CB zas``sRiryGujJS)$3@7;o7XEb>uh+&L)-y3cM*Ge#!N)VUkqU6J!tCD7eA=<6){F} zx;dV4HEH(}an9w;SC$ROMbNFNS6(jNRNHV7@D_E+si)ucFpsmxN6-(k9Ys$YE{|`1 zTU~1VpsA89>^u^aXH8(YykX{}2c%1j?# zoezOR{=mz+XU)yedw`?rhdtnY~1d1K2%(Kh(0c=X~E~)F@^tJ3e zx#bNyjyNL{D_;%E`qRy7qPK{WqpBvxIxj2a0#*PDqh z(X-6!AgEVknL7R=f3ojH#-~3I->VeUA+_w4KAZq@Q2M#1U|OP)!eonQ5v37lnj?{n zERvE%GBPo4NaTHkqe(Dfl3$h}YFJK#_>)vzG>Lf>-)K>lB|YqjHysaMCPPP;}TBAw!rMj+)X8)4}XmI zp<|oaVI5F!m27n6nojQ4_Z4ykjG3bPz|yWFb}Y3{x;nmiY}zhun`}1b|Ap0)MLC;n zHZFbCdc6E#?GeT!zC%5mC_nai%=`fS-qoehLqeZmH-@SA0C#tyTY(u0~nAd~xKm0kvLToxEyg^FU@(+NJtgvQ?T*Y_~d->Sm!n*4b=j z9Ov5ICElruw{(;6YV|rUyfOGt_fquL{-XUJ{u1ad<0Z;h(;XoJRf1q)f_E-ddP|J9 zRE`ny=!`obQM04A)g*JI;lobSgD1cVA0HuyPo%5r2N+;+&L+@Pi13Y5&P&*jP+OWGL6ud6&RtV>c&DCoKp`XoUGH+yy zLiJ?wzesw(Y$L@<1qAYAm-;Sci{qU@OPCg(OGtsw@elC-xuw*e4MOPx0Rp-K2Lj^$ z|J+ilTR5958`;_am%t@kRo4kw6~k99aT_8pD31JoO`}ZSkH{+Gf(6^;+g7>oMoimuL2~ z=k(~6Kld;2p3Rm_KKP)d^Py7Ypaf2#l)F5vkwbJT!e}rS-6&%@%Z~a0stZrC8vYO? z?r5|?96j%3Q)0Q zq+;_=q}Sk6(O`70MNo)9Lw)8hU2-#}-w3QNTk)&^^&iFGTx`}ktk|r~e>%<1r=(UC z^rBkMt5Dq>@y(V@)UsF9Vtn$dEAfo@tNvuso5U=Nx#wuvXX>fyHKW|_bhFG*_i}+T zR3570tU93LLuJ{JA9Lvm=f<+n(cACm(Uu+(Cpk~;XY`%_Oy|IXn1nd$jb3u(A9C5= zJ>XQ>e~xCdgIMWOi3Tk6TyKe)-6$%mF0UHbo!Vwk8gE{trqO1zhJwc2h7Wq zXP5n~&~^MEMfba6P`wp~b*@jaSgcq^-9(vDX1|k{T_MrkkzVgBSJl^bb3g?cC2`$B z@v|AXndXKtOXJU2bIu_8f^bMiDeL%1aZYH?9z)9$I0|Q;y)iEFP1jQ|;R(YWas)zl zNm9NF;hWi`L8w#ZK&YQGNJuw(M%5?TfURFk>@Lb(Pn~FmTN7Fy5oOM)^sUX+hVu`M z=hF^NzM~=S9%#_vBhr$z{yC@(A#Tq_>`nZH#FfvpD{w+TAV|QeCFswbk3dpp6yI2t zm?y|$3cY7EtwRvv7X+!${;@zfimU5Uw9fM8nWR5czJ|N}c zHy7G*tg9sVJ;ZiMkGYnzz4qCM7P3V(y%gGRK7Z;8%4lz#+gkW2zd)%;fk20D$SAip znWowv++;@}O4MT1Y(%S&HEWJEia|Y&%Y)00XhZaZ z)7KB|s?-9R8Uom+ACb|XU{tY)_j@$n%3Xyr`d024QNs zGH~M54F98#ji||#05db6V0@Y3GP&Y%six67?@FsZrWQuRL@8~)(Y)?ydc9&h8LMaI z=4{pJs=I1>?c00m^H(aR7{25j-*e~mjkovH^C<$~?~D{ElR_m@{*al;y9Fl5eL19; zCJ487;;vl@kB`2wH{l-x^$MEFyB_9s-_H0=Tk|^`rZ##1_8y+;Q#}2zGG$LNed+=A zTLp~1(_zuxj~VA@2R8bayUfb2{l5OhoWb0u`ucmT(ie9RW#bRR+K=<0wk^-iNUQE! zto4^V=E`B`!0hYMj9=>h=Nta7pMa@v^%q}?!8l`g-OwLoF+ZBd+&h6i()cMU9b@W2 z*L^?kR2i&}Q(4?Zzteoysz{KU`NS^1SA>URX|@C`}V){ zzw?nnz>v(eS@2|Ak*#-53V(Z%H;xQ>7CP{K?ZY-7- z(ljt9EDc)d=|7_(`zrVxt<;2Ee!j4-dvlLC7ZE|;`?EqDWXPh-W^|Ew#6EMEly*L) z@s)`5E_z9Cguv*R%gd4^oX4un<~I={~R!EQ&SXK zjj@L_8$CqX3NH(0>{%b{;E@^TJ&_sdEW?njJMV%dW-UYI%>O9Q94;I7*f046 zUYLuKIYtMj&P>bCAq*&yGNYXB{a<9yOU5+Q^TS$d8Hgs+A1s4)4blbC>v(ddoTMtu(=@)q zVXQj_g5nQT0j$fJ;MS1Jlv(goC5rJOL|xS5#xph9w~gG~8tv!c?G0zjo+KO#n6bkU z=>ioiXHf>+Ih zX5>tsxb4tdXL$ZYTem~oHlmxuCv#r~6S8zcIAZIizk+(=4g|E#E9ff)8+72P&+k$w z*~?=-UB%2c&Y`YsaJu9EPN=Yq1q=TCw6m0~$b~bpApc)nA?#Bxc( z&Abi#)v`&;ls~La%*wnvG|VDf?DD=$OqORa5GL+W5#59J3wVcWP@CloY3HQCG{zgl zRWVA;7s|XT0K5y@Zm}#GTxW=MprWd%KaGW=zMqAia$6bEN2oxzFs4az(CbbQ-Dbrc zI+V2w-Y;)HyJ^{+ScW@k)`DJrR(LZWCllwCDL2RiduK8-{~Ak z&!tB|lWF&4ZY^SFQ6Yng6?0~8y-=3eMp$EEi6cvbop}%;M$MGTX1*l*sp~9I7(_H4 zgn@sRY1Z@w`?#gt9TUW}=m1KURAo*$wbBH~#mp zxX_ivvL?zWQbZcwi7^15%eyFZ((|^9xt#iw+Y|hKiF0#GRpgONIE)=5Nv^IQf?E85 zc*<8N2li&Y^MQvOSI)I4Mz1Qd6K2`yH4g2ZWnC-kw8_E8^TRn%kqw;4fyG4|#K^;#KPtW?T?Z5<`cRx?bq~6TuxTsq z(2k|=M-BV*j1`As#zDjyqHudnGnBjz`G!t0WPO-dO0*Aosk)`I=laVMdVjMH2MaJt z;O|H?iV*8>ukzi~&$uKhsN!@3w3K?u?{{erg$QjMyy`jQnY3!;ak=PmH{bQh%y|j! zj+@zNdlZk2z9V@zgZAw>9z4hnvdIi(95~AK4a}{Xrpp0MSq=puIozQ=(G;;q7~1sc zb_}~FKh=i_^~Pimrj-*$J(m!`z2}El9AE+Mgqy|F!W_%15!`*3_b)yP9`;Nn$s3GK z<^U(pw17^j@v*87siz%9xywu#70>ts48J;sU^bscdZwHW9t9!rjscI6-i=WaQR9&_ z{j=c%W+LvG`Ve8WNqt|_vMRE*@;Tt1DGKlrEjgOF$G%RsM9ptv4Lc zPcc2C=#;hoIc<%HmVVF|5^i&`Ck1|xFX)0sZjg^lYW=g(ofl0HK4)(Xxob;scCq$g zE^&4r1oX*jl>ShC>a!G6>sv+F=I*#7ba=5b>)N(0e8Eb?5p>3?Z2X_|Ydg(=pDT(q zTA6|cOM^yF{ZMlF5-Ids^`!zS=O@D?&40Xkx{+m<=F|zJMU%~k+c!HOX~IXceAp2} zd*)c&@#&<_-C+;+4VLd`8po>_B?(IQ{V3JA^NOFn3ak zf?s{=vX)sG?pto%RXKdy^qtKsX4?bvIA`OJ(JQLT%37uS`O8wsRVN6(xNP3>-?9W0 zWfw?WY~eL5y8NY8rl5~f>>8?HSg7y{ESJ+B-JO4-ChYP85|<-0se{);KWmLlQg&gj z3F=O+sydm_+&QTMwA27{r_B(z#>a2I(yPfU``dky4?a?LZfT2AwlBEc&9@b?FFJDF zabx8auF^X%Zz?s8Q4FFl-eIcVDQ0Zp2cxMaktt^nzitM0M^^m=E~lOWW%ldx?3d+P z1JxC5p2!Pj??bAUJ&UT*+#`%tJBLGc9(#ETdj7-*WU}KLoC$6yg&lLUV)db0>{2u3 zCF=_0*qbrOCYAMP&J&8kj%)yJci%@x{Ge*;@V~SCNjv)nJSZ`Z(ZVyRcv$ABAKE&c z-fwxISP{%Ik?|*S+kljQF|~fGapehHT($jey5qn%vH7p398n*6`giGCWUd%1-{8v+ zO~xJ7<6q7i<=oS&chSj{$#yEAfBw^%W8akzLKB~O&$R^WwT5qp#Sd4Ve*6q3Jrnc# z&HRs2lqWRhL$*by)w|l^`5VnuH_%G!>zw8<-H~0^uj;OVXYz~MLJP2+%pNQAn%CN~ zzSL@cYR)}>dWVR=OxzFZYft*a*>6~87qw2lf5qh1d5!D6##n}My@{ez8B&10B{-?a zg?Eg(rqer)z za0~I{xlWWD-gU&ytTmEO$)gHA52Kk~q!v=2>o?n^FNm0J!8YR-!r94~x;ZGLNFAR+xOb+c zwos?&OAoR+vM`b_hInN|o>FB?Hu3t(3d z@L7tWSC9PC3ewYx0+?zHB~SD~JoN5#)4UnVk;YLHT4`oMQ?YIh^BdKs4}J(|{l3n6 zFn!hH%*L>%=_qbu_*QZGJ$N+$rbBN@(}r%AJR(V6s@wt5`XG!CZs64uucaZy?{yeT zw7no5sTc9pY=R|Hpr>?~=v(}x>Z{mMxY93$zTF$hlzzK4uBbDSQ$NW7QRxL<8ZrW( zx3oAyc3FRAk9f^q_bh!G%*aOqo(lF^rjfAr|Bo5-JTkz$KPOq!T)(DGGLN1Z*ovwh5iP4CHz#LheEc-o+>>5Tg{Y=nMg`K#xa? zuq)(dhVjJEgao|RC|TrghA@pNUl1I`S$^#ke*I?!6am?eTSf_u+a|(3)~2;+ zt%#Pgd@-vCNlrgf#Gd6hWonz%PD_VQ2%s|oJ;(qf{m0fjc_5b7zTP`K-H0pbYHEldre@;v?zLm)jT)0X;ofA2o z7gAmmgEwU7jShN(_&A^DkV1ECcwsyyR%nDaJ>e-4iC4cPuM+>~j2@`j*ZiQ#$W=69 z+w`zAIg_WdiO1#kQ*Id1Y=nU)0?s$Qa(d!FIBNZo5;vr6#WV(&(0L+I41mmVdnAZ@s}Keoyab z=j+$Zd(J5Dsm}Ye8^0fNpQjYczb>B}^LrBIAj2!0hu@?9TAoNK^F4t_!3c+8u+?SS^uVtn5(A4*d9ut z5P5r+`--F}+=4M678<)OZGTaRklsO&vOUB*XKKQ@S|{|KiRKT0(5MIs6O9qCBB^;e zq$&8uX+a5{w(yuvOOP73Nh+sO*S!DLBaezuhgi57hLy=3=g5VSKmkOBnmTfV+-lcl zK})m7X@TqAw>yyy;xk5W<0x-BI3XAh9-J8b*_{X{3h(ZgWDaj2t3-n(9!4w?JSZNp zZTdM7HS6uI{4Og55YMZxZZEBLK=0r7Byy+HK!+6jyxj1TKg&M~`YlbeC4JX2a`4wB zsD5-HUZPHJ3@P8;okEkH2?G)yPV@qo3o-9aPvsy)li4sRX&o^oxl&0Y}-R z_zWL!!7F%TN6-!V+7grCqj;fb7bTJm$>)4BCPe$MMltXD`a9LK=pnZ9tPgk@}X}3PB>jC zdN6p<6{jydTJ?AUgOxS>unQa1{_{oWUB66G_5~rZDM|WOYGfE_1SKvMTZ)A{jj{UrQCyjfzf5Xx|2iJ7rWoMic?#>qF2hhpb%ZPo61O;X*7))Pd z9_Ivk_{zNKY_?UM;`w`mN3OJ!E-viIf-JlU7XloU_hRKT$VYN;esb7Dprm6YyJwd0 zAFjc_^9GI_GbGE(L(tPr5K(@U+luWdzfi6$7Sm&cY-U)3;I^4ZZ7JHk$23bJ)idgv^O4)T2+bgsL+k zLcL^bW{c&C-ABm!dWS?a4xVR3-lJP9C^4eorRe&-TPw`i&;%WRm;h!(M@7jCV&>b^ zc$)@^*b~fU=PVFTyQ`~s1pGUb#&ZFCi2<8bVRP7#&-LWT62YPG6K|YzrFKrvLdeHC zZ>WW?#8T#pT(*hB^-d}%@f>F~-gI4uY;rHM1ZzQ-{XFou-;;8N6c`8B zuG z{CeBBa>~SZs3Cz7#_Cgdv6sdxD_O`9C09L`uhDnp3@)dc7*K=r{=OX^#u6LN$dHYK zhhx(A@SXNj*0&gZzB+NzsT_h-Vnog|${;ru!w3YNYwfHkj2(jNT58f76cYQGQn_1SuOu)^5ZR^5pLA%Q(7*WgR>%{$%taa zKAl@LM3wgF6=pA0?Q?od3^wv8KwmG|!{Hl3Pu$q1$BPs9THhcx#OvEk&Ro2cffkQSk|CWb_}zNo1m&%Q#jp@gOaPkP%ONGC~K* zz4afzTSf$&@}fWheoluoF9Mf{HQTV^qsH*QMrku$c-s$aCXs@RXTD*_A z1`Dtz`px|C9XFj8+C{H3ObaDncEsz;{dhQ73x!)yA0?MorIH#{xDttoa#xW7Sl`5LX63ZYu7yd1jT;uRcwDQc6XK+7kml&(2o|Pzi{g{MBp8-v^rn#%}-7$ zT_$p#Flb|{v%5NdUkcdY4JV+Ij;JR4$hlq*>}Oc})UIEpH|^kIe;>w-J5x_XF6Gy# zT#uTyQP@jNXD)@bo{#@4v>hI@~dZG_Gfh{H*8r|Sx%yutD!w@Oa=*8xNcnusU*N?P_XT}kw0k`gvnYGzZNND-nAtz7bQZa+1E z8@lrxd?pTd?CE!=Pt-NHS#(dBJli*Tkh2B9=enOgHM6rz$c6d|8w>TBVFxYl8qO-d z2B0nth82OZ&<+4y=)vMgX3|dv@lA}DGq8D{j-RDDTVMB1h(s7H=Y?N*lb-kouZf(u z_c$LSGrmlhK54u1vYz@A#I4m`j-l#o4~dz?Ydos}56yUeMy5DLJUBnpgLZ7()i2DsQoLP*)h0Cw%Ph z*20CZ`gBz%UI&J6NMB_pf>V#WMA_kaHV#>SgP~Or})CnlH%Jo**N%SSpxG0A358U(wxAf zZ1d8Zb1&&6^OK6(-s1@W^-li1~O`w_{Q$w>XpLk(YCKD z!y2>Z0RklL&=`FgFm@@W$8>EVonHCB4Er@=X9TDA`=%IZ*j@Onn5@|_=ona=6~)RU zbyCRFmJ2m$(9>vUkH;Mq=_WB6u`)tUAieenWe905rwB~hFu`1#Ie27&eu@TE0&@+~ zSh%B@7wZVxNip$n0haw2FFjC~qH8qjJUi+J-LVtYoEu%aMo$q{98Q^Fj)$e|*ua5y zmSDTEU=(H>JW;hrdmjd9bfx{{6XXwtBd;Jbv_J0}@gv7=k)%e*V=c5j{sWb5b|^2E z8X5C#8a@uOvxAQmMvvjaCKhyLE2wXrANvF59p>G zR_N|zT>317!)9xJ2YNY|DRHLdc8uE(&~Ku|G%pX@0S^{X)FUX0Cx=m*5Y}YC*nFY- z2Y>Zv9$rW7Bg}dWg8j0tz1E**J&EBtI6P{aa3@tC5;fm&O1$3mY`nkWKoXSs4A;ee z&7@SeXiQeWNK-i0!mYK$7}~Zs7u_Lc-BkFyWZtq(`0U8%4UHyQ(G6Gtpe7HZD4yJF z3qK|fQj>ruQNSqDlSjH1))^uTu*>#`4%?eW`sn!B;OxL|wOrZXfbE9OI21y2#7jhFDG^e6!t#p-b;5 zcW4dh9`BK6X=FS=|9#Skj6x+XN`24WNtNS7Mm5&wBs!;WZCM0zSZCFhLUXf?GZUyr5y5{rK*)efa~qIV_| zdS;UT9X?aBK5ZGJQ?pjgUoDQ>5syd}-7hFBQanjRBm@`0uCA{>Um0D&pf@gJ-fL2k zBz!BgIQW?O>JAsb{=wzm&Fp+&i{H3D-?4Sfd&l*@&{Fs8oU-3@&NoAJa`e^knhPeM z90mTtuv<2lsy3e<0E3fivDvd&Ts=cehWXvexk^jeu#;NR5W3@jdfGu=KARLNT3B0` zZ|(lME?-$*AlR`gu||h3)*Z*~k<-b|(n@Oy%1zd0LFm$)2Ng>_m-nIDYsZlbIAc}2uVp19hhBIAyo`NicM zP;%!4=sGIF?=0X^}97{ckE&79tW1CO>xHB7dDpAyFXoP z9=V0xYo~f+@xB3@VgBk^olx2#+w8H|hvrlMD(NvPkK)t{BGig9m5NfT*7K|ya?2XB ztQyjKRpj{K(;GBVu4z)vWhczrPJd&eFw+0la3L~%^5$r+`+BJgTNwokB|Gt zJjN@f%sj?Msna1_S(;Sp^%3o=UcD7Lj~HsOI;Oz!o8XPkcxq?3=X(J{ zWY4dQ`Y52fx3t*7he)iu6lw0eBU7N~yleABqgh8M$=1^c=vvCFclt%JmbuG&>`{tQ zvy5CgY0U+pIhG8!*>W@4=(z3rzKo(vwe9@4~*SV}#pK{et;TYvP;|kli@j zZqv-hIA)Q^jk`kGqryd$o!MIHL%KP2!FdysRU&2VMakNTkaZBhhk#y7DD&ix zmGh=biTciwXQj0y^I2cbpC9I-1busFBxsmPQ__(pWg<*;f<|eua zymw_UNt4{)y4Jh-CPPs+M!ebS<*MpNfQ_IOFVo%+8g0{zk(2$;f18zy*ZYHUN{cEA zGcL^|v?%dFdsIersqT}qdPz6OF(q1)jP+W#_%a?IoOA~OwbETz?<8EHyx=BK(Hy7! zaCIH7-O`rFo5+o2bD~plO_v(~b~=YiSuiRqcr{5jt@X&%jo=^EuTx0u@#^%n#9L*3c9y+I(S)C0 ze|h13tX8G2j>*qv=lWKe1*i4qICuCYRW)M5xis^=vsW?gJLT5qpBK@ee;BY+{l1AdDCK0Sh6(^7uOK7Y|h47kO0JUG!qL_v+TKcUp z09Q;(D@|!a9a6(mJSRk{YfdSBn~fQhgPP8B`jqu!&y?X|cd}!5Nibz#Jw=&zZxQPqbvIvT4of>s*YGzjFwAL=?ir3A# z+uw5(n0y6nsUrbGSFnMH(*e`xrTeiE!Pq^@`eB0mAJDdx_wL5{Rz3|cD~NL^o6$!c7ENh!Yx32Q+V=M#mheu zgB4!MAv^<~YfYHt0bt1^6o+4Yz(|ExY9_C6PlCGp@8(>CA9Lh)t}E4@>xbiBkAoPD zD<5T6@mdKPc7l81;eCgU@d${_RU$O~B3kwpYfdeDVM47{xUY!n9`Th^?g_SR?c9@n z>4;*j*H<`YFLO_f)K@yypO4a4zQ?xwPSN{{wX~bB+f}}XK=sQ*w^P0sx9kyab}N4& zNB?A|{RDf#Tiz+%&_4^w8vtMWs!UwwSPxVAo0<4G+xKVR_@`($F6&Ak?!^xLa}89z z;fG_L{OOYtHCM5I6;!=$GwaIfYU&rMqZlX$hg-kP75`G5BA}FLx_|L}HQ=@_k?X41 z6bzLv;g4j<{+=d`BXLjNF1E%YwD?#4-o?o<%o-DzCTzX|$px&~syoQvo~F2y+DwPV z_;M%AwV-@k{Gf>xg|^Zb_NGmI2zRU5JKI;Wj)CtU^Xr)%|K3)5h0YrGxlrCq%%a(6 z@W1o#Ft)rec`GSsKPjeFEAXq$!e8#Kzr6=t1uaO*eI_w`YR=G~v4EQ_VdZKBW#~$W z@t>NXUv2M0xFwPQZR-`#vBslH23kDL<7^+rF;q0tP&4|`?(6`2m;sO&MWP)-K4lgO zpjHfHXV75<`Db)k4uPzP4EFN}1i!vI9g;>L8WNfpyu1}rLMEsxtJVpauP&k8JH4&` z&fCD0XzT~gCADO0j1knXdX>NvvV;hCbKpM%Q9znpu2!AZAsONDV9RzZSu$k=3F@~I?!}0Bb1Wj$*7^)f4VTL#ZP!iXpTT_wHkq4KSxvn# z+q<3zpoLm2+~2u^CDL9XKE)EPw?2tmMAFrk#|P0Ls@dL){}HVeGq9lkW)XUsO%&nO zvsG}1fN)+JNSjNK$utZf@EAR;mhlQ++wLJwLpZxyT$b@pb?^T(rD-N2f&>5RCMpa7 zlMY*s-7e_Kp8tTQe9@3%d!&0pHyK3=6CB64e!Mo{S`WLp-m!etY{O#?__}b{>!pAO_STpYL8mizy0frDnAW4<8;z z7i8eCAmwE@b*TYo?(nhM5eQ^9dHgn-D~kUXQ27wi!EGKumcS_06cZ^DW^R`_ zN?XN80Z@eeGOv7}xp+0o2n0i8nSl^(eIHoJ<`l&>;w>25qbg{|W$x5n@%G`-R+a?N z**?N~9wJY{i-Af7|NEz~gq{pbeG_B-Jt@`?zQd2Bp-qY*#~`v7{vM~{?Tu8)oI@;p zb^-D$2yP-Wh-3P{_4GAN$D<#hcvLw=;8uH7H5%0s=jFIl1rgz{A4G}LpjoNiLNpP2 zW|bM47f_%MvGGaC9+j&5Ab`<}DMlyvt@~qU<|^KL#*|JbVEnjNb8fRus|h@{KGXZRGpWp$F8dRtr7$R!MKk zn2h9fg>%qs;M`|(!aZaQq(YHuY5weAUOY!W2J^UvSE$hIRmYE71YKn3ze#o+QJh76wAwz0 z9FxVq7F0}(Ls6EL)JbyTl2eixN3u}yF)iXV7V}~HLaB8#Nxc(i6CvykilrAbP`oI! zc{ywJ>CMj_DA;ATRZ=RbY%ms9ws0?LS7vod8(KdoLpTzJmj^HUcY4(P3fmI|xe4xs z$pMeUvWCK8+e37p>wkphgYvbx1J(-4nHL4noK73XXHVV+5lQL64t>Ml_cH zW1lK2Y;wSIeMu+WZ1OFEnR7A85D$5M=Ys7`lj$GJu%3=JH8_e%lkE`X(y$DMKTD2r z2iIj)7g060XA%xIYl)2GUC>W{4;3VTLe4{oZ%`i5CGp`A9t)wjEY zRpCy~HT{+2{0O!?#*R5P>mQ@nh$zX@}5YKHM8gU8@b53hvCq`|ChT6f$vYfxGT3dSEL7VHrmS=Rq)G31KW z9CTZxHRoTdkr{N$w1%a1z1=iFb8?DdjXSuWE&WL(j6Ae=Iu8;ig$nD-$13Y#7{kAh z2=h%kzmD#PYlH-*yNntCx|7kM`d%b;wpzGrxg; z2~p7v=xAG4$Z}}6s2WIJv%vO*>094PzZHY^M(am%_fLe-82bM$I&%z~N2;4PUZ!^M z?4L1quPDPC*X$Q^dt^nz6BEneV_3WYaV({`%_ZjZSZJuzJbuENpOf;?&P0E@&hsxc zjN!P@H+e7PZ~V1g?AeMoczJmbHi~D+#b*%_KQuGqluYKV6H5kRF(M-zD%=kl z(IJzzU1w)zZm74?qB;189!v_)&lL%HaCJZ;J?3-cei;6N(vDm#Mg}hzt*ke9jeb8c zkH@QB<5sV>HCC{4**@Y>;fq9AEQT47#!+I^AeGXYlYlG5qgHS2U_W-P?i68L#cOib z7CjZXbfa|jTUw2ZBCwOw_F(i=iOS7cayY=^N8UH47&LfHT;Bk9Jet4kB@D53I7@P`_-K& z>xR2>7dxE9CJ3dqnyb*ZZmJ!S4X4%h*UzJtf~4a}=a@AWx_zFqrq$juv-*r_+bYJ| z_dsHKZDDO=Z6%_4=WW^oEQgs}7)fp-ldD5Wz57|vXagcf`qgNrI^Uk2tP@blo^g?v zg4)|<0r8w@Yu06RpP_8`w~DY;U;(x45Q+0gOM3UulfS2j+9m7|Wyf5kEYhHI0^6wb z&Lv7cVVEriWK&D`B>uU;d9P7U}vz1ZfhySZD8K+rC7l4m9 za1^k?|1VuP$Cwl`h5;VIt>3YJy4B~+8IW|dltC-b&SX@)ERFr_!aAR2@fW+|{e)cj zipb-gc>{mz2KKFUKBYtYOSh)WhiNxMRuZvGsT1%qknBAf(PNeJJjegrsYb`Hv22k# zPIzIghI_GC4NP{_X*0zV@3IQ>&Rt}-;c7o@hXlD?Ce=$W+V!HWX&hz2dUYmI# z&sfzy!lMwTTbUN`1eNQCBv!LMRSvKak8lM&Ga2!(v-6JfaefsscFr%H-!~p|@QDc* zKjJ6`pIlH+YS87HiYdCO9>}mRovdX)_#8&Za}C`RS|WeOXQP&RDxGQ!`EIKkIcQye z%T1lvZ+^0m+a7&IeZRL8z~A#ux6%@TyKu+8d0k$^2{FaHfd}GSi{S*%3yz)A*!QcE5Lzzq z7GPC^^D9W;Z<#C5jj)GGCq7ERAS0XhS+mhK0#8{J-5{Tir4Nwx&F8&7%+&;ZUjRlPT>tEm;++mOLm=DC@#s4xW6LPf8`*#Qev7{&>yFI`a1IYN|nMG-iTeaW{TckL=wv_a)N5W+%? z^HF9_c%u-ZO-r4y>{C}1#n|M))yg093g_)?dM z2@}S4u+yNkeT_mL&^gH7fIFTq5lMZ^gqylskWL#vq#nIVC4K)~s&bn*=@q%zS)>tM zD#nT!N%;e$#pWSr(s;|b{;0C_{@Fd!Y17U#)j*ONJfPBR#WBn#qxv0F?%(aW<16bS zofhmHuQ-X>(oNa=q3TInVqc`$n8uJv*{NNEbV9>k_RsW;@pQt2vvYU)A*)Ga*O4bK zNS5{39;x_2ir{&Bv2D%gngEzcTe0s__w3+(s;sGHiEk@ej0=`fuD5o>{mVP(5J2*P z0tq9A18If)FI&s)<7)+S z#|W{l0D5wOTm=yB4Tf|3F-0$yUny}Q$NtCxj&Indh*Ng?9121EZs0C)&Oh82;#*MK z^Cs3lUPztNjD41iiqRaH|I9{2EEhJVZm?|!jGw%~DUNuOm5@p~0%!dyK4^h8^8aG& zoPRqDxNhHRr?%ZrZQHhO+qP}n{noZ^+nm}qrnr6b-sI-KKRwCLNzNZ|PWIkw?e!^e z+tmpvldZPs0FPniUEhz(T$$f8Zm1|$ot!XMffa(IjfwuMwfJcdKUdwtvk%%pL znZ0d8oESQ!d4=)JI#IZSCe2GOO*ypiJcjHQko>A(J6Nq_lW`5T$yH_wbrsB-jv>hZ zP;K5hz6uI_jqM`&vbHuvm(1-Bu2ze;swJ#i)yJuz8N_9S{kx<(Ho|^KF!BqST?ix_ z0OWZ2kL|Uy?u&0X4{BF81!t@x(W(>I=7k2Usbd2haF{`B089C%v3uIyi1uZ@`>sZwDB8nK$(N&oc!E zB45Anp*>&7EXs_`TG+9QziBq3zlI15r54X}SiWUEiT#-V=dX>6+O~guL(e-;1(@M? zPN*c%%!z^QNbiP~&NRx>v-#a>SRihJh_rY6$i!QvdYAEMo3%)6US*B<#1cj@IBPHF zVZ&!yO^NkLWc-;>38c$m{kI5u@j|YaWN%8Tp}>m-X&f>L&@4lODas1Huexp0S0S8d z@Qrw(M+Oc0BY z9)t@7+h9*Kb2Ine4OSWQ$HNs%O;|CQ<1uo@FomLN)=gdWS^+(sJ%?44jd8Wnd|x2P z3gqc_uglYuzw|Wv9J0V`zoW%X;-@DJn6rK-se?+JB^mIppf^f(14ariNK3_%?H1ay zk{6|fu<#LO?U0d)Fo}bDCx-bOI>+>PDYxw`E%I6dH?s$1jP+^I zhfaq|x*|;tdE!dIQIJ0>?xmTcpoTLLLrK^8`qno+eAzR3XQ)Fr?dY z!i^R4fTpLq{&!xeO8HcxWwJBZ z*onD-BlAxXO@Ma`%1FIw`ao(w%ty|kW)sJRG6Ip)5>=f=8zeD2Q#=SqVA#Rja1W}U zTxzAhSTYAGl_=womM0NP+Qf9@E-QV-_URNFq4c8X_;v@>FIRrji=ijYm|!idhD~Fe z*71pU0_Ckm!rTSD&{Lz5-}Jg3(<0T&3u-D!Z)0jI@OLT$YK=ecgGC$kyVV;&nC2Ux0Ab%Dc&w+Sxm9$l}wj@P()sveG_l><%nG z<9a3;S{5;(DMV&M7ZS}|E6RJjrs<@D$tBD-1~8divV7)w!PXA^f7F=%^{Bkwolf>U zIpEco-s;1&{z~h3G9729rD6w~8}w$g{BGopVKJVT*z-I+=SV&Vi5e-c=k0c~b&@^1qiOBzjN{FYTF)A?0=?SkTiTzDJCk#v} z{Fh3EPCkPf(HZt^jJd;zD5C`n0|UCB7$9RxhT}35*B@zokOePjfi;1`;~o>pD7qcd zrVc+5;m*-@d~Z2&%5$VMQx7RR6P@O1*CY9njR z*K9W{_80jm8!p4CwrYycr|u8e6v{-;PpUu-ErHL^1?jFhtQ-F2kx94=b~{iZ*}NBqO*#7+&!*YnCVwr7 zBCSUgJdHJF^eAeVaOE4QDxzOgt|2F{-^Cs6?IU}9=8comc(@T+^+3n!#ER`&><)Q(pY+ci1%dY!Vv=^dM^_}Ii- zR(YLR$CMY3pS7x$!fu^`Jm-+vF%d;O^0pdg=>E4xa6ntf9IadeE+Ja44imXad?m>j zPN0%Z8jI}|s{beA_yZhDy&D7bH{`^69)p<=ylLahyj2hQ^d*S;4DS+NBN#FrX31oN z=)LyY$l@s?X5w8DQr-n=!Xjfrv$PUZ7tX&q7%~NFUYWLct^77Hw#{J9PA}$Z;{#34 z*6|$YF2nDU;A5j`fxJI%d?EFhOzGj!=wT}Ub|q0p$WW^Yq-W3t5|qmlqY^U+aQLV2 zn5b3D?6KvT*^cIZYE=aJ0E#!&?RgbLQ2qO>p6j&5=x~A*7b5 zB!V6KNs@{cVHHRez_Y?CV2AhA>3vSj<&F&Jxxu7l!^qA15t0n0y-UiGZe@i=sCX4F zjLfl?=?yfBU+9CAYoA{1ipOf)d)mUTLt+AGbo@sl=Jrz>9uZ*u3}l3~2;r2l1yBzt zXT=xvn<;;4lrD5*;8ya3%_lc}(vg%4e{GDx=m;D6R>HWYYrwGtxBc2R>Yo`UN@c_t zCL6%eg){L+YI{Rb64jYHhQf;#0O2W29Jh?A;*5o{qI@Xsby2~vlgB6>VQ?iHxi4fm z7LR^jR4RD(Y6RhqD+sty&v$cOEL z4%uI!YW?kE9@{KPv7frqe|+Qy72hNJSGwb4n(-7GcPeYBjOu8>eAhwbmT2EzVO)xy z$A6g_u643G=%Us{w)zLP1}4=8H9&q)$*LKY(+k#Z_PNP^%FJ_8)-dl0?I&bDdUw!T}SaA(e*V3oD zb59=wE?Z@HM&N)th{d?XiT2ys5Q!n~LoeWKgAmZOR%DXhw8F{d@*`hz-XCYO_0G_p zpT4{voRIG{vUg>Cr?S_nWnLH9nONAFqB6*tfFlu#rfVf6Dh*0ITodkepvHl3JdP>Gy!_UclE0^Q;Xc>_HEjijkkO6ZLbB zf(#nxA#7%afGM@4TMDvG@$?`L?IJLv2o{Xm395c5UW^#ol^RDL{fO9!oj=?pEyk-} zDs<10`gRIc^sL=~G93?w2K&SFJs{wtD>d6I&hjjOV7S~CjFna~VzSiceQVHW_&I2Q z^d5A3^ieysOZj$xj-l;@P$T0#jvS`#%XSR%kD<>SUF{4HhJHr~pFP~*O*ef6zE9d0 zf9m9AP!Nxa!N}=j6MM64ZE9L{QMdQxhr`+}gy0f`p?%w{W<+^pb-OZYvT^Pe3UT2&Hrdq!#GG$z*Q#7PxNWw^>+2reBA zgS3`jHEaS0dme}#>6TqPMLg}+I$9QYxH0%r3n4QiaC`;@b$C&}h3e~LA1tALU?IIx zZz_$AP6}Fj$Fpx!37OE9qC##zK2Xe`SAR(!U%C5Nc%|4K)~#3Q#L;i2BlmCn13D?Z zZ-8nD{c8>p}vF4~jdZR4kevxu@Hm<`+sEhw0 z#vwFZBM}}VbQCuFhi`zl62{Wl8cAe^@3_fi~o+ z64h;0E!Mp9_o?Dp^JwmHho6z7Y%hs6?;xlBVEq+gcou@-EdNKf0UO9Sz+zA~H|lwt#?}_~Y1v?$*iR=P7D8@BCxb@uuPRuX!)|xhurMu%TP7 z0uJg-BExHgc`nLKvEMqa=sQpQ3Uqjjw{7eIxUXijaa485RCjCoa8(YawX{~W9SbpE{7U`%LOq8LH!77N$h zBD}dDQKXS(ZpU_j=0Q$?PE$dieo4KdRdCmWAVA7Rbk8o3TB;u{Uf#9Zr#| z4Hen8l)y}5x+cIYZ|F;4am1=Ro@Ux4;KSNchm}gA1 zDJkAPM5HIpF0yDco!XZm;Y>nopd^hGEuLL=H+Ks~p2##0O}S?^M??)EgVR)`EVO%@reQ)huV6B~^WW5!KsT?rjhK9_lfj9N zc^hWv4Az=uSpFtPha)(b&vYbVwJwoirA%iqgghNipaoU>Ir7h8K$UQof69cYCUr=Z zj4J|(#stQH7$PNN(Qioz9n{pMI={T5jUKvO5z2>2upMRfTFulk9=_H3dH416hCYGop#;^lXmgSqPu*D-BohXnlBVLBW`a?h{zPf zE=0nVCd)oGkx?#BZQ6oakD6+bA=N=xQU$z!n!{PsmxAS6dhn9(`FKfObpZcLv}kJk z6U&;N=;3awswRJD@WelwcWZ`=#_93_T5IJlG@9iuHMq(773t>O71iqeA;av4p7{#? zReqpn_-a>w!{;tH`mf;4A2vsPK83qN#$k^KQ843?k9`wg4X*^R6tH2eRT|G&NGyVC zs$SaWk{uRb*1Lh@7`SC@VuT2WgZXD-&)h35cbGP|9%@6kC}8Wja+( zCVS*Og^bK1tR&r;d1Xhmkx0tz5-h;ZZ6aFoYvRL1DwS;|G%YyGB6V11@0esSB?ih; zG`>;T6}zSDTzY(FHX`tR!a!+^-jB%$7Ox?tfA?@zv@qyvVV>gEHC;l1I4zbK7DtaE zRQ3tfVvO}-?t9d8OgIzY*3!1zP7_m?n;g2RwJsfQ30clKDWR%)!K5hG=wV-$D0QMd z3nYFuvTc^4?pm@UPZswBKba;`h%z~eKb>IQZzHTi--9eEs%#Q;Gf^}w=|qxh)zqp# zw-k#M7Kh1s!oULW&zP)|$O3gn^5`7mXozsFvwh4-_PQz54M2F(kx{=V#r{t$+BXmf zQf06V-OmpIHq0?vC;?Wf5sBM(=4=onij_k02#RqdW4v$akWX`Q#K1Q-+BXfg%4SN5UiXh`cWB;0}~uS zYOAj715}Lz(^xgr7&QlPff;ufxNjDYkJaPbUi&$Bl-`S5hZ*f5U9v52e}{nGsR$BF zeC+^zx}|@6aPFRa9OP`xbx%SjUZnR9Xre~ElJ!6r98RL1Trk!^#&m(IjOaW`k>g3- zF~Pfu-K@{bGYx1P2+#JzgLd*d%6r`)iy%I8lq;*hNuLL}^icCY-mdjCG>@;tZZf%x z{{@{e)sYGqd9iLf$%|vB%t@j)%`wk_k~jLR3q6PY&IVHmB(xqu3oP?TXApEwQX|=D zr|bj6RR|0x5{UOGfGh2%?0{{df@NjFpjLP;)bHt>@_~5gb?=y$cSt*QNo|9Rf~MR_ zYW%CQuXW5DsnDsg5))CN)rK9ieajbKz~V#Bi?nM@Cn_~=Hzlqs#KHfF^;r|2t0vf+ zC5|ZzkW*fO$2t|8eoTWtg{OH8fVE~*YKdw$!;VRwmmZp*;?!b7Zg=8m%851Yz?pVV zh?ln5evfYF9^GdVFx9FRs{wh808P3IG z#GzjsYEpVEJbAZ2kfWLS^cLkaJ0w^FOgRvud!%Ms=*4hzuZB<(0 zN@u!GzLi=8=afg6@E?e9PpUV-Z8FHvs9QPgtJvp?v%}r7-{qxeCw(?jlK z65+TN8Ja!OnssaUXKutVeKdUUm;PR=@;&1B6Qu*zc<2ubxXzM$=+nfS#nGJ*)y! zAE_G~!VU{kPboA*C0HXlvP29AJ!GE>(@Y2#^*nGg@T2HiIpv{ZW$Ih@n_RuvQEztXogOX?3AM=BN%TY zL3Tz!EvC1l9y{r+dfzQu^B`~7Za#?JM#h8B^kwgnC_pG(i8tx(J9?|)kuzx#yGq!O z(V<&p%ntdO>-R$q3PC*Y-vFieWNLjRKlsTAro+L?P%3$lr)DPY}&8|eF8U2kKy zNcGN2VV}#vEj-GnsrFo?xa9K%Y5?gPqHY#kkOxzxr^AXjjeNV5trSD;;^>j5NPIRbqk1V!GMCoa zUVeQ?lbEPb z;f#Pqv2;0i%#}>y%k($s|7!oiqR{HGfq;ahfPm=!tM*^o!tnpWwWhTpy_J`j`A$q* zr12ymh%r{`AP6!LROjo+xdISe5wyw1K}5-z3`__1|5n)8R91KDH=CnwS(Z!km*=Yh zEVr$ywY1Vyt+cL6s+Vhhznyln(#F#nlFB}LKaP6-U3Z>rHRk;oEc4<%PkKOvnPsb| zk5alOCM!RSUftd_HLK{WfROA4qh+V)IIF&lbGZGNp{~i-A2d@;kK=^a!R??mbhy+cZnG ziKbckVveqC!;^UX`TG5;(|XBJbg8CY7PRT;cV6yexqqgY$9wpXrfj>!v@FmgSp$=_ zsdf=hHF2lPJiCKUlMt@14XoP`hZo+~s%U+QU{g)N$C9>R2xf| zmpAubXFo#dEjmNK-J>90-#$47-?>pf)Li`gyFtM-B3|CZqd||R48P+eF_UK_;E%RP zUs|Tz+xw(@?}=Ht2c`w?i-QyI59o~NF6Q3HJLvn5lsLU)7Coc|-PDX#$s1IIJrxUI znyGKmk`GnS+K7ZM+G%WG-y}aWd|$e0t%WWcrLRBJT)JO{Y2QQ27;HuWefJd1sIY>B zl;*|^_g_l28uQ}Zh|$EVpo7&Vs<2-SN`K$&n+Py;|6Y7H!p(p7*c6X;$D-U&k) zd!WSw1D_U%*R4ml{>Gk0d5x^uy-4Eki|F2vD5;=@TuHQG zKDaZ7iEocMy)<|7X_82#szvrcx2JFD@pKrpFf}rqFpsf&2p%~vF?VX70*SXu&DE1f zk4%56o`yBG4uQa9EQ?|lY!)ELxOvv6O>L>Qh*uu2md*h)x`3%*#1 z)fy_sXr)hd42&GcYKb02WcAmr{}$4oOh$%dp;s|2eht-h22~JhVp({^T!AFV25$5k zoff`&7iTt|iDYHVO8EVFOu3reiG(faZX`c9n$hejL~eiyxrku4v|>o!(1R9>Y-Q6# z!(T@ikr6SpLQ*eJ9B?z2%%qBKF%a0GTU|9u@UcAbD0Jr>={O-KgcX#8&q$+|oE<-B)y_j zmv*|;Geb+WpnfQ_47U*qX&y5|n0je0lRkvL1i6#-2`2Y-9nGRK2OEv8DOK{R?dT6- zgD$Cf{(Jx$qa_6EdcL#~7woSqp-D}^jH%O1s;H6}&hCUotWfv03|b3sL|KfrE%k;q z&6IA_B zRSbMhBYOflVKIR+-ZkQZCSvd#_S#W~=~#>wxP~m2j>gk-I3m87#=L`m;ikPNhrApu zMS0DK(I}Z;-XhMT$mutQi&kYE7@Hka+GZnD;q0Fxd10$?6=S3b#+e|2{7s`19MVP& z>WhZUa7Vh{b<$(4v?x(zyPLPWBl+|<#8xFqy)f{yG+;2L*>m2>f5@jlTm*h=e|y1T&P(j{&4WKWGMCIj1SsSAkrP*_K%@=?W~+_xtELOn{V zESE$HO|4bgG2*g-*qc9sse#*)S&25#vA0R2!A)2)V)pc@%}<6PdDIcMhFJmErz;(A zF$zC9?#0RYkmE88NSb6)jinc?vqbtP6JjoJ$VRXub;ZQXw+Z3d1h+>;kJ zB_G&1MQ2BDh;mnVDmrEuTI*bon88gX*zVhbg09T2KlkKRi~J7G3Ds)iweYTi|;70Ab~})=%2I z9Y~imS=Jsh0MAZDlI#5TT2P?7O{>K;ENLsQc$Q4w#LPC~K&skHg#E=dL^$Md&bhau z+(66av|K_?w^~toWx>Ai5-n$JYXxgoV>^!|bPmcaZ}Lma1k{wfQQa`gNsAaKAKh8e z+CI6G9`x2a#0EPvU73cL`K%85M6-_a1n6`LZ{PZc;S4PJDp9b{6|_SYoj>#Uy}4D@ zd^UEXQc>VDNE!p<;^YnH2fAmnh59PuNIw3(9z$c!#D@KvHa^U3c(q*$`_+(73FS#! z1vLs?lrXYMzc{9SvdC4x_&RWY{VRsi9McC|$-G7$+AsfHme-pP_#j^qcnoK*ZG$<1 zGalmU!3A!@X#!5`Iitrm0lu_jNQ>O$V+v2rR3H3hLpC^4n2rEj=2O*^hkKRJV@*K{s0=*?W&adVk*=p@DN2bK^HT2119t!PK zfk+~0vi(&mlrw5AaO0Iz8-1(E0x3E&Hg#o*?It?YPn7uL3hmOL3+37CkzJ(OuPV6! znB__RVGhDz@1Va*?O@%}qNrmR7muL;C>1*))NfS>k@+J-=BcGGJ(7@12C^OtGcLd zU6w6*qNRjTta4ESzI9tq7!_JY%$QJ}ih*516$|@%DDm2fT}9@{Xe^^L%M3PE;o1^e zwk39!-0}|A1_}%~mXzj^>4wt|GS_-BmV*sG<3s`8~cm&C$;JFa-YZ6Hz!>r6mImV=< zys_vUg|jq{im5tqA$OLUJ!nXEG?0eIP*rJ3`Bl`j+p^38YJpu9*Q^ZFvSiE>?UEg& zAq7zx77)H}T()jmqc+X7ePBO z*<&alMq2cTS*-q-@qtODN?n=L?l_#Sbi6X14$e8r)tyUmZLQP<)nEf5l9{b^_NI~3 zYUTn+P@+BUj21zwrN_MZEk;REBF~yt_`LX(d+CuaQ*Nfay`RCf%Z(QWT(a4SDELgq z$ir@SKI1UEg?HupbIW2}!@?xw6I-056)@V+Dcfwj+ygXB{W-OGIP1Z!q`!SX6;7vK z6NhzFqB+A~TqAv2nQS{r_F$oUf?(CS7Q@ks-4oxVXZI1EIfYd1GYS$e%85reHYiX=9C`&(zVuxug~O)BtI)|I z^W#bID>VP|b<;#C<4Gr5UAadedPE*#4YD##8-!c`$DJ_! zEuq6OqU}9?{ljGZ{`1$ylyeIXjbP{qH?L5~t9KD)cO_6Y^PE=NRq@YO7fb@~GX zLoZg8v=!|B1dW_^Xkja3Cf2aCh;>MeVccLMv3J#W-sX?Rtmtc$?HKI9ddz3JSkv*F z!>Q?KtO8jpbo;uj$X7q7y#2cNx9_3)rold>UhY-Ldc## zp_;_xdEitLQ;z&aORfBV}m%w}1X`d$}kJwB**$ne>f za^2#{wLc1VAY=Fjw}vDK;VD=Q2Nks_=njJvZIGM2_&QcoINp%V3cz+?+whhk$$&yG zmifmP;~z}d`Jd5tV9#oIggvi?&-Pot<=pmt9_lEyr+GiAq}U{D9Ze;=7W01M4;hW7Iwd@je=OFZ{cb*~Sh#$O(@G2GV zwqm~43TQ_dQ^BO1SS!-0s!PCiLi8!r!hH3wj%J;FF5xhyd@5-%H>A0o>|finrwTFG z44zw}Y`VS3Z@+c0pLz!SkLM5iQ5x^p)75L#Im75A!`Qe&{0Nb~^PFGhOK;^&18=h6 zcD5)!lpdW=ZimlqvAF`&94Sl&Yl9P_lB1}e6(xp!&s$CDaO=T+wc5iZH&v8=!z183 z&uiQ+JC)Pr{1Dg;#YBcV-Ny`D7o1*6rIa^`I|K~Bw=EuZ;sx_IMIWFWzP9;i-2w}k zafe0n0`}7$1Epz2T1`3rkg%A>8NveVFTFz^(xOsHir~#_%cQ z?i4#BLND`mJj`7Ko@o(8MI4U!F>`Wu_xvUFuAB#!1$0>WF5(# zizX0ZX-XVA0SF$bg6qpo={11mrWjcP7(2Cr@>nFIqG^pQfXx*Y4g0o=GgR8<^?6aje)Z}7Ca>KeRP^@{FdBvKzTC3Bu>y2BQD1g zyK%C|7)4Zqj4Dt8;ufSIYW@d1f3I}yX)>Y{d(7FNnT{7q#n1-So3u_rEjMs$XuZH_ zW>@SZG?|)B5f%6H)U?7oMO6a_4F?R6QT=@W22>O+qBl!EnE*Lyk%kP_U#55Fg=hax z*Iau-`x_x7hM?PD0uTQYdOU)Mh!MId6WU0Fb&n4nfV1?1;!A&K>$Wd~q&#NI`Xm9K z4%dDfi0Mi1DsrS-wLc(u;On#Et%qWdk|rzEVzRzJ<%z5=g4Y{lV_v0gUAj_cf?cpF zdCF>@A?C*bFVSejtdyzo&z!YqrU3>}SD+{jh&k4;dT)#ovo0P{QJ_#iUQ#Q@9+@TR zBSX;14Hn=F(f(jY`GyI8rgj{08l$J{+tm~1_k|R=Q<*-Futx$J`p*3;$c2D9yh%@l zzME*Yn3D@h0(r6jTS1KeKeg$fd1oeo@JT>H=)$qP8^6^V6wW@1B$yJ;FZ^?%DC?Tm z=2Y93dQT;__0Jqnh}uIU)os4kw5DMhb~; zz60(N#WO!m@ihv|Or3J7fSQhDa=}og{tY1`T{j5H7oy|`vhuwdmh6on!Ogt-JG4we zFJSE-c-M!I`aAd-?{^WzXB5&SflYB-y#7~MkH9xT>J+&HNwYmPqlJl5&UHTLvV`Xn z@OfDba#tV?cbbn==mGLsG#4S|Brq1cdf9p7kv75 z__A2Q!#|*UT-|DdJ{hEEov^?cTqu202@sK4R{2L_MsiwlhPhtB+*Ek{2sb*>7D?U; z2Z2hL%`#wBMYRL8LiNK9fo>_C;_GbI3cJGLP6Q!@$F!w3R|VU0=@on>{B=&%0O1LozG+X$wDI75SDgG6QM5Ep|)7JuRjpy1}% z@r01uGcDb@r*|RiN+Oy9$>z)5YYxVj2E-Oga|=>hVDL7>z!rDvKkW-$@yjOp;G@kT zq|Hm=G_-K#{+_$vtA^i$;O@5!bn*J@bEAYMTm{FcY$0v-Kf-o-+*Tc7v88Kt#DuDC zOHE>E__e3=8aEhXd$`W;D!v%pr*_a^>1vKE>$$upnMrOFc4RBA5=_8`GgUz~MdgD5 z!e80VJz3v8;7}j5v8Eo($yXP|b%7M91If=VkmyQ`+#zL-R1iij!;NB0eR!QUqQ7|y z;#~SFT-K_7Dx|inc)e;FI~_+|8vvUSWHakGhm7b$I8un2Yi0&d(H$1lxoj~WBqu3> zS8n3wIIi7RI3!Net5csK>vZm6Ja({YF2lK?AF9b~u}b^u!bv#?Zf&)wkbx=RZAK#b z)*caa&d41SRi6@8ZjYZMA6A+?Ht42yU5JbhnrL^MlvHJTTD0xir%?}Fp2#jt%NyhE z&54Oq@^?#+q$}awDLT|1xWc+vl9x!t(g?R=WCJEuzeP?eh8=xxqTmMDo;VU#8Lur* zRx_E&NB$@P+d^DF-qdIAm6cPYwX|uze3EV~V6r>aP}kFK@}z&TNAT@K1uMV|RBsnW ziZ_{fpGr`n4?y1c27woyBIZai5FxJ|+-ITC1k4^nC}gQX?Bec1uk(e@K_yniCEmi!5t#5%X&+Jp7`80 z&J$ljnt49*hhj>z^{-@0X*Xi|e7ov`4BURqYUTwMxCPXT!V@VH6hvg2KO2AABLWFv zLv_r0dfjAmGJs;KF1~TCtJ-CyXHb6P%0 z=r@P5GY!t%yh1SFT)_{i$Xn>9484NJSJaMlz2eC?wpgsVkR#Ce98}4E?KS65>>z3L!Vky8fPuNTJgqT3NOPP)waaQ2cAK;(1*!eJE?A~ARPPlg z^iSjPCzIgH&gg3gDvSpMSGS9`5#?)(6^=k%bBjx&dg#PEb!2M#kAzl(chkw|2u zqFBVq93=a#PYE|39rE5JBvveQi1B@SW79W+q&ET=egMTUDyYI<0-{gcnlE_w(SPc9e$-8q%~Fq@DA^&!wEvoh2j?QRS}ep$I7%r=YR~1mmw?VI!4&ye!okV` z%!06m43_LN%3=#JERn}$j+$kni;OA)WR*ZUH5F&pEUM7=Fc^+>>6Mq}TM+IXoNpcG zI0e;lr3Tg=i&;01vi6<`(L`g=Im+$?a;;Ip&@MI80D-3d5$_HZDYUAOzl+a3mGoM5 zF)qT#P&fqz{xl%U#RFe|tS4^@0Kd)(-EaORd=-$gBz#yR5j&s|J21nljLw;}kQ_2GNRY0Dq@NqZ6Eplm-8ttPG$yqOm!~2m zsdDHl-&v2@@be%+TAF&OXE^sxa+J^vSGnliDx$7Spgru6bw%@-n>0BSAI!O-u9HE& zF?(xv08>sYE!hrsn zRbW$#TrNkzXDK6=_2`_keSu#L3B(1lhTLPA1POag3K3X`T;K8OYrdL7(^Scss7Krr zO8w|wvP$6hlS*>Mru_38br@313S@9q3 zFNaM?e4_8=vj?B=Z|6<7*X(EBXEv9|@upY{^1S=kg4oI3D^6w~@*(5=VA#L0ah7}g zVE8nmBSsBcrNcqxcIhOk>a^06TNvJnQ5S9{(xpk0)GF?YNm#txtE0kh@8~$}H+6iS z>Crd$Sdj_|+UW-Sn&{*4BX@k2J4nV%x+L^hcY-`}B{aw(U|Ywq@J zx-@9xw-Ck-aawff@o`2?sx+xX$MP_`q;0yFTU1`oj9L^6U6QoQqX!njJwtfCi^BZo z0~g1)0BzX>H@@Vk#KkAaw}iOWJJ|bc(G17#u@}me(k>gYQAyM#-_jC3~Ux^M9Xk5c4%$+%4Y95wxyn|xs^psONfZETpBb(n7)NO zIlc37N*=l_mg7%G3CGHoD7S%6ZnLj0^#)=j$%^|cnRLxTR?ro|I^06qk~h4)G=ykx z$hkx%MPoM|S+|1!k=3QA12nBA#4`uj(jvAbmN#Ks1D;>{&1oP(-pTCWg1mKrygp?% zvQ5B7pgdmgla!gE2*$uHTyr84?fhhc zzDUN1s=Bem(P@&GVj3IDne`}g3Ca^Y!E6CN7giRk=0>}Adtfkr89?!jn2{{_&nXO< z;1vXD_<{>0`{07?IxpGUMhE|B>i$Ho%buh#f%le{YVf9J$YRxD(c%CkxIwiB^3yL@ zCHnaW!SlQ~jg#G=`FKPw=m9nAQDNV&ss{g&Q8U3N%W9I1>{QPz`FfJ08R0e?YaMDd z?ZVYVu+5Ey#^~2|aq@p?cw-kGujw1eF&66>H_i;@spei>AH=jP%V?6YS_KKh2o#0r zQvB4;tzkvffeZl3fa$nNNz#94F%Z2@Y9b51i|BOcg|8TzF`VpxE%Z>Tgx2CstD=GB z2ry{+zNQeuNsSPHZOl~rym}cs8o6G*roY!ES{BhLR3)VB{~&n<`L}OJV1IedTJss?Jz;SU{OR_irWzMGB!~x zl6{}AhlS}$g9%_w*-E5|iIhdKzD)xja*Bo}5=o2@>a2wIwhV{S4f8!>ZeoT$m;Q{n z9L=#H0u_*M5^h^*3SNtu(s@nE`Rw6b-IQoMLE_Pa@(V(IRis=^!u0zJQ~-T-QNlidqF*iCnLr6d14QGx&?`YWe2*3_P1g(qa`S ze(Sq-W-GNXBlI~Ex=o2kMoJP_`s728et~Ghy6CKNiHVCk*Y;eWPt-Ka8TYfVi0V`_ zsiwe+=R>I^B23;NB4<^mBbb)$jMsBsn4UqpBkG#DFXO|> zb7Bxay(@w>i`)M%g9npcLi{4dM(ru+m|$>%iMb0PEPLkBT@!a;`#yYVEmF8iaH85h zB-sV^YF@pJu$~a3JX}-|RZ&(s_yEitCxG__~xrY z(wCqg%NyeRNKvbKn1mgaklfg*FR)PD{Q=%z+k0eSKkysjqc*xwc`q?TnUG_3g9z9C zpk=FT=)Oa}d(ou4qS84MlSQB`>xmY*yG2qTnQucZ*WF;#d)ka20F8)@4(U~i9zbTQ zhLhfdEqS6h5axCDBU%DJ9LAUE_s-!?<_9&O+5L^MD&5bA>4q^RC;Zl1Y8QXeu~{?z z`Rb9R3*gKA0Is`@dJK^8I<<537%g%;<3Wk#QHCbH8kX+K>tTK)VQ8d@zT!<=)(eM3 zoeblr)=xj$2g3Lw`W`oi?+#kZ0V7iF;znV5o3*|STHq9CcvJC(EikR}3)*4k zNaN*qz2bn){7AKaMsNQ}*1sH*ZFG-NB4q15FG^zVHSpm#sTssMfOn3ZN28An@HfJkcy}0>Ukm7jjdcFtba2C|70uB9)^SFo z|0Zn;vv7=cv(}a!fh%xaQyXeO?O5#2k#h-+Sy3>maWU1fds+cqNyzc6&`OQhrHX2V z;Q(+Ln?qy)#H~IB9-lY3>s^~&)+|NxkE>w0q|7|FkRIN>*DCog&??a7 z^-wZIp1+o6jT{Z9&x^^kGpGkDe6PI`ycuUibT*m$!sq%g@m=cpe^B!+C6+Ncn`5~A zP0qa6>N-f42qud-psO!oS_Di<7P1CD6^SnhtD%?VbSJ(3Yz$@zUFkD<_WC-$bK$$F zm$5W9oK}xXRu@5K@}D3sz8x0*a{i?gekUSqJU9Fr_beGRUsKM-$+`tU>gVi`{w5U7 zS-%kR?~h-8g(nq&-a8zoo&6&&(dkarkw^G?+VbtGEj1o`m1tZjY3z4-4|B$Z1=J^m z-6tA>rWhMS`FxD?&loj7-Gql?+!SC-0500PV1qTFzGad+`TeJzZC$H$wH=1 zq7ZH+DsI%8AngJk;+7Ifu5el@@4Vg~?X658p`xy2v&iubE<9}cR2E{akB_+^^TT-x zZHu?ppK4Pw_ZkQrbs5PjRc2Z2Wv=_2>zyUt-af-bJO>&xBETMF&Aor8#J>UOBm(dpd(Mt6^kU9YzX(x$tcW|>ngj$JTG4zzfKOZw^BC8>WpF&)ssy9#0iG|k@DV#03 zQHoIT@#VPa)|PZgN7+wAZxoFt8b)A3$2^+50YL} z*BvA9V$9xsq@c_5_feo*VrcWm2=}MpX3;ib*dIB_e0foR0%LuHp-%sJ3ohej#-a3i z#}0GMzs754R`Cvy=%_)~JOx`W1v4^4mpbQZ>0hJ=^D2%D+jVsY``0W_tY6?ixq!6u zmnWj`A$af5kGZ@QbcMh}H)9Sbe2OxTdHHDE{A18&yQ3jnK9C%fCEoBerecq1TF|8V zq&2OlZ`SJtb2hP2(N^Zm8~s;taYon8)FW_#)bSf|2=pA2Ca(^$2a-;RmEM7tote4` zS?%ET<+D|8L0(WR%8FQ@J~jII9~+pM%!4ZRl6Ba{D)|g^7V(t1fM@uM?1PI!^7%u1 zQy9$6Gt#%?ZPS1Z%#6yVW*lq{@KbuXNzzTu&M}<}d1XQJ>wIe38vP=@D#2>`g>7bAlVW+rtb>&zd-Z#($kL_a9{9U7?V#x8GO{)msT+JjBnXZB0=8?+lO|3(kzvbl~^J~hE z8rexjQpG#QdGG$Oh0R=73^adp3JmOuGn@Hu-f!0FsYhHj5@R)w7*eu1q2xEjG;D@W z*RgPk8#_t(5>V0!7i+rSChgn>-W8*x~*sQ@-@`2_y9{PSIcc(ea#Z2 zRCN;zsZa0~J$FDa#nrl^o9*fDP66JjGUsOak`7K-*T>H9$qyv|R1PG@@zL*;KlKhbpPJ9{(9xvsoMXcVb1;}(R_M5+!e(Q$NZjz*VO$6Mpc4)S z2hNj`@2{Z8Qryf^Ni3J_DH-h%vi2p&xoJpv;A`_nfz+c~F~5?A64MYVs=H@aGrZaW z>bI&V4B_Eyg8`*g6b@{OgG#wWYeFhpZ;@7|QsFV~7nA0B%QB)oZN)XQ-{89%E}GpzNvObV>3FrS`Atk43R-mWa&oph=<;8cT(y#BPYOy|)MXs_1W!;zsN8SAAF#61$rp+u9*NH2N zdM6BMbESq9P;+;Shs@|-8?)vOc`E>-UQeqEj7XP#{vjs6cr(7QuMkqbvx74KYS2ud z)=nrr1d(r~=VLckpu>J&z=k7o&vU48bwz*RKBSE?xri;Ih_V~7czMSj!`Kqvlk^=x zYg?Inu-8+Bp?hJIkmC2t+%9XoOMN?~%P&nE%LXmla%EoP+bQuX4cs1$=5m~<7r~^L ze)i72Qp%QBe;pru>P9Raqgw%Cnbl(I3mnuAK1qUgLf}$~m)IjRk{qE1*$L+#3HZMNkn?Cvc-muppU7cnn16 zibDEA|Lue^-iE9H&J=%SVND1SVR3ZmdpUf4VMV~QCF+$dy_abMd4cRLB&~x5*9y&l z@{sI<3&)Gy*aMd|W3Boo>2eX`Ufvk@tFxILR|u9iBZWSjV}2~m`NE@y78kG1k4qUq z7xvDhT=%a4q_ADGkgd0#rQC0a+G9+IwuI2qi2Z%!UnUMR*xXSdg4+0NV&`uMP*v1pN)WnbL(L?;6lkvtq^mRSs1V~+is5Y zwO;}qpcUlgCb27>35Q*RLAb2gHCi={azj(JcG=Q!$}U1dt0ZujQ5?a2z>-t_^8sX1 z(;ZU~Qhldnjk6AOwY14wD`(R~=8VwsC712qp?&OX*mr>~<`D&A zY!S7R)H(THqw8W3W+NY1omBtFIc9iilr!TUr&KZ2i5e_=F+Xha+>u05B?g^)LsNWo z|Koln!=1J~AE;CHhXtSBKD5Wzv@ZE^W>xmNVEw9PhUF;E5S|<}Z^?#{z3?tJ1(Je^ znhCkDD^VP~5}p{-p*f_UUU-hBB>0{~Gn~)T%aDRjU*RnXuZdGihQ9o=kh_c9i!Y|X zGAYS*!t@mA)Xfb|1Kx3`$hMoulh{&b7kxlbySozSMZzZb{>r zD6Oi~tvBD4>-%LN>$HD=He5qDkkX4NhM7Ki&;T|?S6Biot$)2XAN)|d?1;MT2z&D$ zrtgH0S~e=_2YtF5CCInV-vbw0pI{*K_uX*|Whx1S)R=%i-kW}zXo5}YT}nq1c8|jt z1H9!U4rxCwDydDd%hyIynwoNQch{M3ifrqrLq^0ejZ8dXV4RTC6c?FO@yc_kuIro7>*cf4qr4Efw%NXz3gW1 z8?IJnV+Og_RJ>)yj4Gib_TZJ*IEXxnq+($92`AKCy)ou>YrPW(NCrI0(?dLJ+jO{U zmG}HrpP-I^k%%WK=Kfl!n)$-Z1%z2Xq)hia=4cJ?n{TvPY`EFbrBx`N7nJiVf;ozO z3oE)1%7wBjpiC;RqSjmyYZ%!^>cIOIRPu5?<>bc}xWF71-`FL47FJbsENNYAi04?1 zsSkXjx1aG;I5MhnXS+LsTH!2-;ulq*VZogcO$bs{?1tf8=z)pLvtdVKPlwiVCx#O} zwU3VvdWnu$MM8enU0mZNqp{gmxXUU+u_}N82_0ShvO=zeS1||DaJI4ZOx{018hEJO6GlrRl(S5v zB+002ooHvRWjQrdKK*Wec+rI@)xBvISI z^DFAwpjK`1^E0^z{m;hdD7TH(4TB5>)JXIH{Ym`aNXu?5C{NvGx9>Rfq6Be;hpDv&+VQBaNfwex zoPmEGdO|Ivx6J8v(Zv=%hO8vB(Nl?tlum>&a7;w@W|Wv$D^PBIg7JEgh6~2wMe%|v zl7xtqa>9uV@l9k!z}Y`LFHfwAqn@IV&yS}cGutx{yDl?)9#7i{1b!fWvJstuY4VM4 zpliN&e#>2hCr=Rckeuq??@buMU1!5GuL%$W^h1;Sp7)U$0{xX0UUF;#YBu^W#yC57 zd%LQqa14c>|E@y47zY;mTfupi`v#tOsTgS1+<^w@2O8EdwQ8pVs*f!jcX<_WF&906 zvR&^x9tLtP+#eaIcL%YrIE)xi4YpnlncYWYwD0_~A2pKz)uoS$H$geyGD@>Qf^3DE zyvuE>hw5_ttx`dSyrIfx35CM<6$Qp@re!6fZZdq#QzZOi@7M=1Ys?8cBlfRa8$}*+!Gp>e* zJpqa(cQh($Dgf;2KGwKjU_Hqh(c;E-=FDhvLmV7*7-QB#QYOT?(h>*fEs|B6Qvwd} zLC6Y&&6B_0Iu8=$7fFl~FLk7#qf0!uWZ6fE%ab#ZWgX;6J(k?aYhp%>6FO*!J4wp_ znl{nsdAM27ZmgqKcGj`1WS%inoL|HI8Z0a~J9lO7sOGWL#x|?^6D9dpZO$v6CSz?uZXkSFHTF8aXq0`CJ znlUbyV8;~uD--4V7rC(KS}R0x&QF%53xPwC@3+} z!uj!cV|jOBH%kL?hAe4$g(w()D3b>b*^Hq?${}{~RC~-2Lr;hc7!ykmNq5rFfF*CH zKCR=jtj%HW(+s6j)i^NMhbD9@MPd##gHWBh_RYsbVrN9$Mi+g?8FSLP4X^U#qsn4= zjU*3ST%HcxrbMCEedrgb9AYA%)fpQMVK z8&bafd_F5>AiW?O+Iq1~z|>j*)$w>*zvkX4bNJ1XRljY%N-_PAfdvgrq?g zbR-Wm$Wv9`NIki8nQDk^n*3B>xH&~E$=a?Sg)qim0AFpRt zWzg5z$%uf|kINn(*y-Et>RoHV zRLnLf@;2{Ib8*btdSucRv)A&Tp3t6Hm}txyjmV}HLN7wmEMduRcCK7&Br%4%)~!8^vB0E zjK@zmjKs4aW9b|TvpFU7hxZSM`GRm@I!EYQkC{2Q6CtgiB)E%k53!o^*d^l)d~z`R zq_gD7<=NLw^a!(QU?UH*1Wz=cwe@e^B+TF%PQWUZ#1*8bch$}|m;t_R&tgjfk&nr? z2+_7~G2!cL@E84!vT-LhH{@E{GCB^#sj25brSHCq;CdN!dj3_`e9PT* zW?98_-x9j}#*fLfGJSlUgUii3#V4c_5q=nJ)KhKx1&8*A&3Ep7&q+u(>2DSx_k5jUgfcQo3>AZ7)@k2@DJZdY%D5d8g6!(xHw)Il7*kPUT ztnA5-?~gBsPa2-1`Dbm25B=St=&_I|&6npr;>qhhN$1NAk?j2;UuBxdJEHiTo}T)w z+cuHsSIs329@Dq=U}gn9*KfCPYoGmB9fX2@g0SVvj~HY|ku{nM*fAnmxFfBmOT-Eg z`=}X#-$p?o3uGz4aU_BwbJOgSK!F)|hV0Ue5NMnThl+9IoCGRNaR8WC2O@hxPa9&(3vygPrW29@=|$yfB`}TK$jHb2g`DRn^^D7at`E;GWLMPN+Adl)~Ou z_OD;`q2g3RvQM|mG@suWWGkxA3oO?)rOkpY*Y;%1sqVFa?Mtf{@Qv;WcZZT^JIx@N zdN3U)Ecy|Hy#-ja3HAnN>XQ^>1a0kFN9UQ|-1yS%c*)J?UENMHEx?wR`L^ zX9uX*(>=4OQY?*?IEcylCd%1%^V1aiYbn+__A5AFTN|Sdh{LbJ(}}b4HR`k` zy45QRkU64Ol#C0(dYN`mbo+*5iHJ98h;tBs$&9^ekUp7R#`WonHx7p889*~PD(5L% z$xip#`D%^=hS{wWMj$B06i)Y6BpAvOaOQ!nA&cYj0a}2pJI4ZKGT7`+?;a#(jG1<*)UZJ#0 zPI6fOf`G9*?YQYJZcD^s&=xqPkNi=KT=~1KbWdeBih7>6alf_Qns*=VbOG>Ipg3h;+F+8X6icZ;}QZ5`=G;o4~TynxK74>$+IE8K>wS) zhM&Kdf9OYqkCKYcKK*3ga+D%Mbi5o3DVrN?v(H1ugZ`C-Ei@>oXKMGUq+cG=JE-b` zS8Q)z^s@-}Dnk0E{(?7M$raFJ@`Ul5E*EI{Ss(O$aqPX!`Am58x6JvR!Ky@?CQpO& z?gy^SjfH`h@~(vxp1>jt9ah#da`n&U*SkXgE-*vm3-t33RI_)=d$0Icfb^HavDk-s z*bNHacIn=&-S#Eke{{+?m3-rM@j|Qf;4X zCF(nZ&%x&3X>eHY>a}-j8_&= z*$A_IhuTw|7;7O-=0?VUm4s@x zkn~JL_E&(qJ*M3+3vr38T!vBu)3Nbks)QiJK3~^?AFM3r(s?&(URe9M@)MMJMI0P& zR(@b!&`cp|nLyGx#&r$7F7mq2kkSbv-xQ5=8wjB{9G3_}HC;P)`sIlWj6Yfvj@u&8 zRGZUc$S?zNvAKB;cM?+6v9hF`6^L%%D7IEGjyzNcgiKVr%A$tTGFRbUO)I8%o<0!1 zH)o4&5sBUX!QiJ7Z^tZ4RhCUPN+;)^LKi@n0iu!On3S|lRf>HHwMshnOS4p*j%@I>U%>zivd0R0IGwEdHJ4kOjU@tOU z3(N=sUudx)FuHIhWPfNFpL9cv=BM^3qzba&D1<}1ziHV6l>Vt3U{M8(2I30d`X`<3 z%>@wmcTlWlAD>jLfAbp#{6J#5HFrXc3bftEYtM$IZM@YGGOtCKqhM}^Wt-jAwEP(| zPcT$b&*YB(V!k*Vvc3E@j+xQl<(Wz^himj)h80<=@bdQu^Ju-IFpjjKLCdV)D<5MZ$t%&Xx*qP}13P+bjPy-Q#Z*RKsqnjG0XbNtZ6-q5OO3djAbmAs7MFw* zmqs)p{Y`~D!dosDGSvs2A%>711E(BU?aVKm5vA7vxjJUNMJnT%MLXzk)%SHpkfiq7 zQZ>SIG3sd5PtySJFz($odHd0zwY5Ob-!4gT;VwR5H)TKSnG9AHa=P*M!e%ZchW00m z-&=RKrtd`)^Qv%^Z;<+33E!)SdyhYy(2VPMA->6T_GtVM0Iz8v>)vVeMfi97hn{b~~ACS!-if1r?5QX)w*0rum+MQwqBN8kJ?$~LC z4dD%NpLQvtO{93su=pw2C5ofXDoR=+jrD$(X=LUpbm8#z!lLNgpi@rzre6yY4A2M_ z$E5NJP~?5~(J9;M)EZ{L)>tK;Saq5TX?a7zH90zFBg8I^Gi% zl-}J$pS``e;IPCM97z=%qy0CiQgR!P#Rvw6tFHLxZM81o!06A1i*?p2)%kW8^mSXv z$_Cr1k6<>sd&+8z3)?>}$2fuxt&v)-y=BHYcCoc9+RoK5@3_;l6e&4aIQhe+9=v`Z z!K9NJn0j}C#W>S!m@;r5wZOU*&e+fdCvl3g_+BVzwQ#x348{!a^&7Y7Lab15;xc=!2;X~IL=p&Se#TLKAJZOGdl=$JkuHDJ)GXzuhEvv7 z(O}xO-hHG|exm%}MiAfOa=ARy-d7o1AL*xJm*^?&(P)&KZZOT*83FaEuz z9!Ug7T9AnJNJkUEkilD+gh7UyvA=PK$+QgF*5R_?($wzzbS~#B3@eu^)~xNiKlmbc&#k9_#A;Qa-Ss~H3A)e(>@2Z$hKlk9cT)$&SX4UiDnnB@l0ZgBJROZzCoR?u=r815Fd4W$q_vRQ& zKll7trRxcl0d&?)Klk`}T|f8m7@9%v>{y!N`sqQJLGS3;OTXq}Aw@s;wwT8BTZK>e zdLK-a8UCc4li}&Ekau|?Ds+l$0U&POjIU4aOPk~{8JdBntV6Y{?&aB>Y(vT;*RV*Y zlU2%ok3}35zqBHyPQiImjGjt=X-38l*{0O+$J9dFJ=GL0kxd#sg_c|^$ux^JN@nG1 zUo>~a48b~~on6K*%2dZJ%+8B7r&Z?KcD#ptohvbiX5CA82EIIp!NxO)uuZWqigc4| zeK=8%c%5{dKIMveoIdRedb|deRzvFAdc22zoh|r6d%Py;%6q(rXyLQOH}oW6gv0Yq zTzOlawoISX#((%~qq+ImMGCB97S;|v#tKr5BU-ENX39~|n3@Ve)DWvGp zQ&d32D&E1iI!q!L!K8zOLmVRqXA)S!-B1Iq7Ja^g8b@XvVJEjg5jF>|+!U!Qr1rJZ zq1nWRK#=;$O4G%UzPj}x_1xDQQ*aWhQy6t1h@)Ux z=)D$lXXFkWg}MVhP9gZm7iP_6Uni!@Z0)(6f{K8j?Kc1i8K<})jqV{#Q?E>jGPOlG z>!%F#Z%e1>_T_50s)5I5wxga1CBC$%aSP@16JnMno%x_ zZ3g*(4qM)!?Hj2vo8sjexD|G;ZDjM%wGfG|GBVTEi0Wv<-|Q^2C^}sRI)LOGMslrY zr{(y-Mrbn)hFVp1rU&S=Y;PaUUJOBpViY@Kl1TL9p4bPP|1qP(;kqcZwXtXI0)s0G)~i)E5kY*&&Yb?$ zXDi-(*C-A%GN+0a#|Hk~$D7q~A?XsV>Xd5B7S#l;Oag{iZbcHu8yO2iFl@*}xF`1a zJ8jWi7X68pofHBn0z;H8l~3xzm4oZ=NM@#-Oqz=Ir}J3L5DDI_0R-q0gOzpt-#V8| z5*5544!TWW%f|Cv7Bu4Oc8?L2NP$rzsZbwlb!&cNhZ%=UN8vm57VAN5HwPIKGF~mk{zm#T2hWg_~4_ZL`cB>aI|ZO=Tpdb?UcLY%Hups&Czgkaf#bQPm|c-;X=wMZ(N3uc7S{{yyhcdzl{dO zPbqB@?ipq@O~SO)qlb?B)j#J6YJg}P7hTqQwsd|bf(*U&_aP(q$O@fdBP|RMIb_o< z$?ts=f@n!yTMv}lfhy)2w%p}HulY#QOKQ6XqM8~-?Q6IrLLmJZ-BT+S(!3id9T zov1u5AKq6fMOhkZyAe20Hc~Y47x96`oxeWu#4{KToQsWc0PuWxvy0xDlE2Uu88cNx_gQuH$u0g>0H zj7^Jz_sbsAc*J+Q_5042D6*Ln$=FYuV?zMJ_zlHMhN0-{1I*m`9E~KU@(O0@atYS1 zV)Q5#qfWdHpAPQJ%R)dWCui6sY8HV3Zx=tThs;#2*)GlaKb+;0g##!jK9@=^# zE;LydA7Uv;egqr+7`Swtd|i_V+ZXY}93+5m*9@^it3a_zt70&f<^^SiG77q9lxG!$ zfXPB+>gT&wx}MM$9bcN;dP~|I%Xv<0hxuQbmhA!3hZ6NT2=hV#PO zrt`+y!q$?J&lO=|cVUVmUcMqxWy-@V9gazUVv7`d{Egas0^x_qsn(tod&}qn;SPiR zoYRGs=a&PQ%2BEF&Qa=8=q1nS!{zIR-dpC$+db+1PLLkALXOjcgF;`@{{LPo}c!w~1pS6jC98Fb%JKd7H9f2;t0=y-b+ ze4oi;7>i`+1P7%?B-t9!OWCJj?aQvYnxw+AJqf^)-JwF8dbhTL+`OB|o%q~!gIfr0 zK-&mRe?z6*F5VZM1)TTBWPS958neH*z_MJ1F4OI0eBKAJa_+6h5Ax>8DfL%jg0?r@ zO4t8QVtkC8v)S3buBnHnq#J?OSFP_*vDL+9^q<5$(AM*jv4hh$uqcBfIdndSvM*>E zsoi{sL~6dwxw!*_M;Uax!I2V!IR-lK4E$)4Pl#{8u*;hQx&{%TyrFgCO)X0MjV>6!NBBjbTE==jo0JJUwTZyO}6^D|ySR#U_|n)5M9X3vH_> ze7QoSaebI0WXWKaUPBYej@2{L?hsfFZEa2es*u4oIS9*I#x`===A!9l{7kK~@_eOg6p)sh1Tm7tH{(#LpKumZ!C- zz2Zgw=f5>#k8t65dnCzs9A=Sy4vUSXSy&BL2$=Jc17A+RMx(t25`=dpSs zxU8te9VKni>`i`ZM7XVn+>8tPM_`p(f@U0qsJn~Hjba`SUpkSS6M?6rgr<_?n>Ju6 z-U`9Z4LCg-2HmU~kK14!)&u7I$x5`8J?!8Z>SM&1eebR$RS{H_jjb|-NaU%Ef#2NJ z35#$QJcsyfb6>i6aM|AKF9uw2xdnvmHAXvtnO0;uVKU$9Ucw~8eF*KoZI1D>l0k;K z$_Csdsgr3*mqsArk=?rD$xVe+8^gvn7$RyJ4T=keo)fx+=TeKPzaoE;;gQqQ+C-~+ z`{$<2WZ0xV?|i{;w^kMJ-Hx*CswYQ^wD^Ew zgy?2CkC|LHuafREQ2v)TE2o}tfi~lLcw%F(wR(kX!w8YnMbJUNE=e~lo?E^fYDUvm zeqz`xGOa3|Qtt0;MkrvM+R35EUyz$@&{$ErL?m`$wf&c+Z?<8qILGR8b zFwdi(0my$I><9X;R_{(GFyJsa0Or*U%piE3GW%+eJQz@!RE;&pJ#3z+24-hNC#$Rpsu9ulVYBe$(XC3^L!x6UdM`;Y6_potuCY_XT1Br4 zKVqh%}jPrqp*Je_Gk}q1qeCe6b10KCMpB&VCW4sTLz6(Qi8{k9XJ{{t+cMDr(U8KsNozu&A zOUaMUzshscNlMh!pvWr(v!N-I&kao#xhjk{@sm(dERtII#sD_oGEtT60=Oet^xl*6 zNXhfa7g4|X@=6LvI@saZL=+sQDZ2hjN)TNCUUkka_R5h%gRc-%bUj~gJwik+Q$x&* zE9;X66qU$5vyK!qo}T+VP0d{m>~KVMGpH@-#`xi@xd~g&x(c_t3ZMCMqwV^PWyOV5 zfH2PmXn>m3D?Cd}G>MR4+j>Y5KLncSD~G>W&Ur*cx-UmtIBE^-R_?)Hqgmb409W4PCn3NmqkUSp6dmXTbKG_+X3f7o;T-M?NME0gxf!Gf8M|A2o6o4a4- zY40@7&&HYawLRC8rT6=Y9BMpt9k&8XD|p9bFEvvM@dI>H>Gul9loWlTi8!&yc(mijQyy z@y;ex0nTqlm2n+Fu=?0!Aw5o+Qkqiac|!#IIkWsUwo9;fV(P>W@OIx?9oTU3T)}?v zdCMo**o7GGV6XFaxV;o}hfoN6$P}*SCHh7MCW;;4+Iyh!+(v%AaMH!_x|nyBYSsmE zQ|R>a0i<*{6kY^l|5u80sfxaA+S!A0hisb7nX{h$est$Tzemc5!b5iDzRj7op8jdy z>ZMZ&Zx|KRHpg5{tY8UuIIgU)6FALdfeqOf`967fg!erC#xxN)=@GplV2bG zai>AdR;BZ;24KOK`m;-yS$E(%WoSzV2Wa35%$23fmx+D1(1FKAH)^MyQpT{8??cV0 z*>9(*JdqGLTX5W8&HLYj`eqkurH*@?CqF=?Vp$<kf;x!frsyNMYr&m# zs&+BN={25|7k{@xpladT%U7%#-+T|oGd}z$c;Idkp<70_?6AstR^gaZC2L~dyu+uR zS+MIb+>LOPP=|kqP=%EgeF@pWxp-8_IX;Z%S~@ta*GH%u%@-U+WuD+A`Ml(Ng!(em zu1bj?VBnMx@lcdJj8)i`@5@UmAoW}X#Yss~A>@cIK4;37SW>~nxxZPCU-ZDbd=L^V zx4_LVb*UMyUcPQ2qTrb=+zeImLat`g3cxPbD;LkoG_+n$x7h z^s=Ue|7*mV5#>a0v5>GpI$SIjDU-BteJYuDM*p5Gaw>xv-mbdbm+j)g#s4Pil1~A4 zgqqozqL$vM^UC?gloco3C?|(ZN5u-`^0#tag;xyUaz2?@!3G;e#xUQS(XE<0NL_HN za_N_LwR{0v1v0pPx~4HoJZU$zlsB5+E|NRic8unT;&wjmiy=Yg8o$XIMA>l})LQY& zK<$KDsUWIOU!g?f>);W4omRH0<%z4|<#0{^;)@hLz7TX85_!qk|GAkOk z=DN7W#VZm!=k?KGQaUhh&H*iX1k(Fz5PrK$?mZnKxSRxkprBNc4G^)djfj}0dW^nE zen|u?oOSUJU1)Ngg08Fl%yyZWV4@p+-eFoF-RbPaMh&eFV|0c2c{Qm7t>ncLc`LdQ zq+lxQo!SYVC>ij+q^uO;3QThx3(To+c+b<*kTw`qf)27kB}{L*pjZPO5Q5UN;N(dVc` zQtJ19+sm3&$vgMmDZd}2_2QoBNZaGz5zITl&*fz8iH5JgKT#K4BpFEjtXj`mk*vrU zx{v{KYVxcwask`;W?(1aUvG;q50`-ekXe{_A5ec_M`Hv5lrre|aA1DSbb_bT!Uh4h z9-;St+vkh$qX!Vj_5OCyMSicqo{h@(!GfL8oB-zZCNKvKF6?_a2tUf*37;;8CgxKd zNLR(LOeL>>G1S_Xotz5Na^e*d$Q%sOuH?wR7-X^N*^FR65@HGNsjqz3jbUb~VnRQV zhG?FH`0oyePICgj@A~f+hEj6|zbANtGV^xoxxg!ZM(_@4n$X$+t=2`*!0tFJV zt=$nJYroE^Jht(h6ZmD|0F1i@u!sE}@{IyyfTv0D^de|xVJI>efJ<#4Gu@yBZV&tJ zQ^*C&*&vaF|L51&HZX(SejeTS4D36oW$t`Ug9X?ZSfIpaB`@(D;?oB(0yHc5SBN4N ztZ2x0Pnl+r=9~Z`8sLgbO;g=D{2|TAhwWNjUqlwvP^!|*?cJfq>uRDLH5Mz1$ ziRO1guQ=^9jvLRH`nDWHCFm2+vx~P_w`72#!yLhW<#$B7K0xKnP4vitQ2c|1ICQXX z-eJMr8%F-`repe#^lnjae}G?jZi&Y^*gMZx?vBXp%lrev5`TW&xd{6?$&DC+3!C3S z^AlBVL4Z^G_q5VGf0-be_IvQlTv`{#{#3W@Cnd{IqRVS*_GE2+_^vTS zzy$x`;F~zG&IsX+dGra03HV1$`_`c55U>f^3$t;yv#{JDt+%d0P_|jRt74uGqvW+Y zOmm*)ZB`5>>=se`H6U*Rr3IKp-MCVi$;&&yuH6%pnW-EQk1xm_{p3*;m+&2>;5^_i zLM=MriD@QgCW#VniYG5JAf5&pg-)nONGB!?Bz#JEE!qJM6$F;eB<4Z*1$0hSBoUu0 z`VO`rBN-q%@cH`<>JjC{q5$oY<>WMI7-G3Zui_RM%|Pq3ZNs(K`o`f#C4$Nk8w5gi za>BUOj77eVxa}XLhQ;F73f-EFi&AcwGx>xXr2@P8FLeMes3-pfQs8PnFT5Gu1V3e3 z;Z^MIq@p*_tX`dlACxEEgo4sazAwSGMWHXuop*9A$j+aKR?1o7H{F?N!C%Kj$#9ee zA|K_HF9o`>58;%j1zS<~G>SXWoRJUW$uf%mc*oMoY57&+Uik0J1zW+)Va#C-NXOvG zIEppHyfBLN5We6Op_G?O&_6=S0|A)DcLt%(uoJ_S68U~e6NidniqJnWO73YgDc>K< z>g|H_3v_sEB`w7>^QEZ7GWb>aM+Fx^dHK1g`xk2X#It8yM+62|FACsuv*%iPurFaD?^U`PV+hK4&?lV09`;h_ z{%-CY*BG@P?XfpB$)~QKbj{Awc;gCYcF{Y=(V;(yi`Xp01mZ_nlh{enk68-sMGGB=857BRat2&NJ_wNBw45%??xDPtW6% zWOR69FA+2}9N=I~1MCox$)-bn!tMrY5N`+n`us$43_(Zvj(LMC+Lp{;vZZ^#SAH87 z%k8uJSPB)}Da1AD?I@GGmi5yNM>r5nYYFJ|j6}fmv%5%CEoJj|&FXON?Vw%uM%R{^ zj65DZ{#Zh@yO>yN{S!Th88q{fJi+i_6}2YgI7o|sF4gIHs|@M98w6Mds*`OTf=}GAd`K& zTAF#mJ@$@Mj)23R^30)8DW0zoEvbCMIZQHhOSK4+~+O}<5m9}l$wr#!D zqx+0A?&nj#=Qmuj=Zdu=_MC#`Q*0EExJq5Ml2Y{9X?lmWll0?O%Iu9$P~}@`LJnf! zNVZbmW%7_1pLi-AE|k8C+Xt3vnd`hmEo%9Q0T$#J$8bt;>-QVMa&fuc2;BA&GbO0m zJ)lv#`3D=gV!_-d?`UTy?Y>t**G6&{X>SiPBx2!mea zcc!e-EoBbd6~}ijO>r|Ju`Y1V2ae?s)BC@>0m%1)IUwmvl;4mljwUDv)fABRWKV8a zEXcFQE?za?>Gb41-@rWL?21C)$lft;3U(f*IPProU0+q-{p;)$WBmb2eK2eFryQM>-Sn_bzsewufW$U*z5Jf0E$u zkUw$w$9lxBP<=AsADBP+vQ}r_I0q)^v4TIXj0k#+VGedM4qi=+n0~f7g7p}W|5p6a zXNBTOO`o^-*6O4k#>QK%J!Fr?=BOQJ%k9Rn&1ZF8?vE|c^bbSM34HX*EAat?uXX1{ zF2=vIHgX?M$R5y3RuoL}2N=MyIFC_?SF)^LC*us#5eqxorfxIQF}o%!qqdJ>#q=Ij z3v=B&=5{(KFwD2DaLo8@U>I}RL(*%o3MU7|!rx*PO?`}`*!Y=;kK-8mMvP=;$;F$v za>%IYyTTOu!CRam`ojaucsF$eU6spr@Vsv=XtG*+`myK*u1G;}`MRsTX?loUQ#h&~ z-r}&zZ(hB^9>9rdILq#%7;hO4X&207Ty$BzhXq)H03*Gsl)as%LY3)ruSFpe%{Id_ zhGBj^uD?dPDkgH?N3HCFpRzedoR`pV6J$R79J56=S;>=c@F{gk_(bd{HgtYnieI6+ zaTi%R%=EXDsY!-Ze*v;8uY5!35sSkz{1kiVYqQRHq2({#jRU(rNO~me2KFS7`=TD) ziyUgdywHchA5vf6sJAsvFd5ZfpbgiUDYl#bSdY;AO3$AK-hVq8FL1jnd`Eu8)C6-+ zxGPlK<0Zi_WM+3Rd{f|l{gKj9s5G&2^l5qZ8yJON=x725C-4#d5sv5C&oaf_UprQe9C*bO>)?Zge-A2;Et{_p zbA9G3>X_o@2k@W!G2cWOuwB3a0Gr?d0F3|DevF!hlew~y-EWhBdpIVm=qO|V!tjwx zkQHk8O2VQhYHXq<%Pgw1?C~Q)`~wTyh$@A-*eB~yG(pp0-{9YPP|W@vw0#=IzP*eY zUWktCQO;lH%Ef0EE>K!WTiwt@`F29$QKOQjaEi z>FPY>4`s(|(UJOhQm;#^zGrQ$k`7FeM$=I|6+O@>9rU2-CKut08jUzzBU|OXmJ%Ka z7`1Km8oLH?bw?)SkN*-1MUa5!&OJWO@@9w%4|WMT?(w5F#3c}KbfETgIZSd!L$z-U zX;&zXqgY=|qfJf|mh(a?xY^mHWphC%n$3a+{q+fFUm5iu>Z&R(>MEP^ZG#~-$#P1Q z>;l}ZQnalUwM2HBq32fvEc7Hj+``uUgI`&TcZjx7So;)`R0Z91 zU&1TLUS!x6y!*{g%cyA0KsDA$x**l2;|2xa%C4tV==xE?24%Zu!g?Cd$;2%k#i$H1 zWbgMI^G3@T($_f#Tn|j&mrUEo8=So(YDPz~MhHOUtr5GZ-_}d|({L~(p2Tt1V&fD) zidh9i7Snu3Tw>+eZ~Zd}Vz%J%_`p}pI3GY)_JfT6MrnhY+L)g29FdL!49a&R4BWAd zniXqWQN`BGqb|hW;@nNjOk82tM5>Gh+_NgZZr7MdvG!Cgk%L~{frl*|28V?OfjK%w zug0v|^vw}7ScGs}R zFNYW!-|~t@HI}@7d3Vl;@Vo(X(f*BOzoO<@Gh-e~0IH-pBbV4?PFW(^#;TLd@%0B{ zQ-=zT(!Rg11;Kx*lf7c&8&LzCpe*1EzgWa23q;iJ12z4dO#BS3DjI(^fF93Cr$pXw zPVE+org+_rz3YBM|4%L0!d!bx00aQ&0RjME{V%k@##+wK*n~vP!rIBifrRltdZ5@L zHz0tJH2@Ym7>7X6xr4Y*$be{qAPa${gakztWFB{r)t}#hyLSA>>cqmL0s+P67c2CK z-X93-_RQ&GZEa2C>SN>r+YjjeYt(=yTsNweB7=d!LO&zlPTY-X-DFl(H5T(RVdoI$ zEaKMfYTo8H&z7Bpa4q6y^?nsj=j2NNS_K zw&rpcQiQwSR-1COxlvAAqfqY6n~)gq5L(p1kQ>fU9Hx-E;@xATE~DFOsB{0E()l5& zKn)e%_ zT|uY~?oG=)OfKafD+JXSr0~(j3vPA_sf5}zpq6s-G+h3lkazB13u694?)X1JX8Iq< zZU2Jo9SJ*aKoIoNO_b!MW{ln2p{*?dSTTX5$NJ1f71 zh)1`}X~s>xVTOe8?Jwhc+fbsn7C~M<>!|OTu;EJJUGmm z=3A?aChsOKb1iX*b>fI*i3|4cCY*k>?`8PPS&Nymvpi`s3qi^V8V?JtQ*AG?kwmG| zzksJiLkt^41<-h<^3dB{?&#`}+cxK+S?(SF!*>=kX<8xjqbgAt|2}DDw&oQWqo{?| zlzofGpxv+p0(+z==N;sqfGH*w9!>wk9R>Nne8tTF0j#VckF1FDZEL3A9;HOR8(xq< z+I=(G#_#L>0hbp+PPr+>7feDnFR|wm5|fApg$c7Oho#(FnO~Ma8MnD7*LP5@Pr>$; zXVv=6y}sJ{_my+cg16lroO z2h3Qs@$I4yIWB|u&KR#T7Vkvwk#Zp2nG(kK1&h0oHpfso(3=&*!o=mI;=K9S+hkvc zitE^3ZvYq<{w}QVw1El>k9qPDRmAzT0aHg;qk_J91NPxabHLhFRdP@Sl z=SN~`>RZb`r0(ZIojEm!o~f2CP${V^^(;a{%<0*asCiB{!WtKEc9KDxhLsd_U{80& zTpVyIgGnx19$L}S-Pk6A;rfsmxoMqJWX;md5N~W4r)vkL%PeJT{5Vf1fDae_R8qTW zizmC7RHxcYtl$%Md}P%u>{#&LABhlKoZ&238Y2XU7=u@AmB=o5+3N^_%3_vJzwsUz zxayvqqy(OE^cHm8-{E&aW}sAS$0&v8DAfms+V%+NeNZClBy}s6<9M#|!~s^dG9RcB z<2dYQ(JxYygH{}3GKo?gB^yXo);H{b7H+v)OmEU(W$OMvDHF^8DAWHQKLQXpFVsSi z5HJC7BEVuoQ27KxVPKdiC~({1`T0T$w}4(KhTf1Uv%Qj~8=2YJ*-PEN zo!x-yV%@l37!rl3ftV2?FfiB{Cgxh`-C^t)jY4;Rf;%u3S^1SDUb=iQa&GGOawLRp zO1oV5y^x~!b^#tQ)=4|Jq<8tU%Na`oMVUs z))n+*(H0mRt|kbOJ^^TTH^)F_<{}X1`|G_LP{jUQkvq-jT&a(08 zK)VRliMAj$BDH{EQ8$Tbd)~=HjcqNVh-w?uHws-o0NmG)Un;9;DNy&a|9ZMJo&CY| z<>288R{%IuG)=upvAJ$Ijz1w^CI)j-vui@X$w`kPX`Klr+kO^#u6RW`sMY4mv*JRO z>8Ug?8OCH10PKVYMs!h07YAAh%LW(LEf2p)39skQwre%^kYew}KcP?Ju2R6cO!-Nr zLPTUKkc{%qOD_s3#DUgm=jx-g1~})K^D8_$=Vs030U|NO*>wIJN9Usw?;nZ{9WR@)dvDLkvW9xB#)TSq( z%h(`u+6yWpmLl#-28lsjwH>XNgA{*0JB9hriQZ&slt#LUZyK1CdO>UW(WGNtLbzn` z)Pf5nbNwWc0qP&E;Qyx`97Ug!D-MN7BMvg3 zsdA3KwqN=W#5CJ+mJ)es{u8&uN!5m_Xc7jNop<9ug?onKB;NqONq4+9Mp5kj8I3a^ zIXNfp+m73gKHu-(zygr+sDJW$6;%)h&_;kknV=+#>Za-n{X)Zs?-cxz$Vg-A160yf zIG#E17;iNz*A}DUgg@I3Dz3gIWcQ9oe zV{$um;Q9|m@hrLbl7&fDYLJWXkRR9feE+V?r>$o z4m@63+TVe~hK(?^0Mjlt(s;5MjD{4!qe^q*d1TC1q3JP`JkzqT!xr=MJke%ujtWOl zx(0PdP`66qs+Vnh1p@}Wxfz&Bih`{LTbQ6)o#b6rw0gm<=S1MtC~aNmop_xaZ4%6StA+<{o(A@_G9W=G-l8)lprp; zHaPpnTxEwcY?a$-#Yo!T2NN+1gjA0;wlyRsQX>HUNnjpqCn50u64$>^6+mkF&0X6Q z=tbc4B9AI-7+%T|xXC*(k8+2}AsSwephnTo5X>bUQ4pz26Dg&kpM)5pgdcHe@asLw z`3yST1}u1UfXW~}LedC5^-#n(5rR#SAXXuq0d?Q*pNav|tlU=gw+I=b0021u`$Cko z{d+C3HL(8Qyou~zTJqT9DBsHs&xQ>c3?XbFN*VJ2RuPnhBuAUjY`Sgsul0h@4!?|zWG<_cf)?r5!hon6Y0!5FH@Xm zroL|rg6tpe*!qScOv87`0V(Oro2F&)D>#W^eF=< z^ui4_`k-EPe%%W6Wdt}wI=c_BI$N#%ekd`bFD4_Ea3x)o;c(eru(8uC%`-%VF#l1(9m+yix-Sndk2lE9$R!jt2^R%JT5%t$FFf79eU z$dK!5H zmkUX{D9SzVR(x)r>I7jm@eHxLP}LkQF1Kk#PRW_UZuBS=;=C$Vlt}N)H)}vb%1*`$ zy-2l&M71M;TVQs`B3}CSR+4977LB_vrTD5%e8O{(PXMuRCiGAxMViIiz~Lte64PSS znzYIuC<#e=Z?uwMC|X{tO>biMM`-&{=-0rs+*MLZJuTAqokzu5Bf{t?L4FsKE0r?T zNWtHd8lE=H)@<)e?reD*97U1GDWHY6ElKE{D*0N6@R;U+ce?C}12M;ZPHCZ)%1}bl z_zh({oW|xpRN*t|@ydsKlP4=QF!qG$s`CXsoxjhdiNd2Y7b;H0HxLqJl}suuO3$Vu zV<;uc&ZjUJPKTN+oI2|Q*pGy|Xw+`M1|<=}xI3GPRNcL;B?_jDRNW&;Iya$=rweIs zz?6L$;5IS2wXcl8`vImCcg-p_op@6rp8a!R=%V5fEvhr_ z?zkd=-L+*Ohv9LSITzGo{>kPI0@NzvO9hb867hyAQdVk7IMKoK4iY6MknI8@`GM#U zF0Q{L{H^MySIj1br>_&29-^7j>uIbU={Xw%w z>!C1}090CjdU0?Y9}?7C;z3PGLnOwze`FK{U;PoL5rHrSF=bsuY9DsXXQ)|lgb+`x!VfP2{`2V`fFCIH z8W>hf$fDpI9u1MhCIq3d{SKMU%$ACgX&)#iIt-X=AKDq{Rb?Vzo22zJmq&_alB-BI z+%t|jf?#?u$RQSm98i~wfRP=`JZ=)j?mcX}Npj0N((<+UcA*8-agjb@iXU0RpWN7|$^GX9z26VH^?Sa9NZ!AH+3| zt$9X7@B|&MO|GS%APyYff$zQd@{<&Znq8wo5-%MWY&Q9=d5NYDj8ty1ZR) zl`rUjN?$`?CHH zH7p{pYz@#+M9a)66`-XfX{$a_N*Y==C>xkBCTS=U3gP+k?)t#J5oEn?`_N?xpjZ<| zu}Qu$zX^vOZ)D6;U1a=Zm|k+YPrOdJcd{IRzF%f~04@iVu&BtmPMwuH<%$(l?YW}a zWGd36_JHraxuP+%elcbayU3I>q>6zpQ1PK$aH5_Jc?b@PqNWC2m>}}g67eJDsVTK) z1XSlu98{NUIc`45jO1i0aM>gI59X{ydL zmanv`t-w|bWY*eT$7r;l*vt2Q*B_`xvYwP!Xn5F5_Ei6sujQ|Ohbbm2=SsI~Q&}$5 zZG1r-vfcIx^hp!YwfZm$&2}By>DOutwKJ=Ny^KSnR_zzcy|%t5xeNIa-5~J|jBJWk zbv7HmwX!M4mp^=V_I(qK5)|2oMBF^a*Uq5ihO3(I2 z04nm#epAS0+b(1_b#bvzf+ng>2MHmKf*Mi~z`^kG<05WezeaBUieu_JXlnNj^yxUm zJ%IKYxDQV|i`JU%w4JLP`C97CJUGmA;Hr?#CAl&iqL;l0>Eo^GQK6C~%*{2;BCu{- z4BA$+WPFA;`UJfnTp3JxiH9Q&LH%xhj9T~&>(h@il^;yuDOwgXfH7B#4UF~9n5VCX z{JX#2?N^J~mSy3v&ChFn-vwWEVL(C>@5xvcXX-+n+u`03RiFImS|x~M->3O%BqC@R z;+?i^PkaL|zuDPvQ&vu9c8-KWPF$`Upue_E->d>4DmbXtij+g6fhOu4{Z?f%yM^{* zEr6xLQN5V!rqB8&(HkG36=F%q3PTxTC|`SgMw#-1^k$yeMZ9>4a#nn5vO638;{5=lQg*3@2pwt`rD38d-oAn1&LM&9Js+2l> zevY2t$l2bfH%SQeOJB&1)F4lnD7@bU1G|NFeHTn4;IVt^7+w^M%<1%h1lrKCam`a<3XZN@7v+Y+PgPG7`2@^Ta`AM2 zcLs*yV_R<^tX`y$H*cwhU?m}iTvm1TixLzYmePizrs_(zJ{UR^-IX0Tfa`rJH_x}X z<|=C5P`q@9>%i`gz3jv`r8DW2C2H()%X6Cdg=dEIC2Q;JphnLZoB@d2k58sN4X!t^ zT(vVg_UKj;fH%!zzI_559`p0qK|0}yqESfC41z%637BzfzCvl^_yy!4Ybo|rw{ZelHJ;q# zVJ7zAB%NYIJIF}FxLu7cs@q1n0JMoCC&%U86w;xIyUsSuvE!E@gWE6?<6>FGTH+23 zVPj}9V^%8?2*=vIh~SwnY=nV^oFQ|^Elf_f=Psh%y6sj_A#b~L zjc~XlZ7mdA&bUuvoPUOjnWg@s!gs(jO*(2l_7y}z*Es9f(pUXRlhho|an5~V* zg$>CviC>5l7aU53nKLb1)E8#V%_pGVx`)A zZWl*d;y|St2wqR2L@xWA1XxidMnY+qFX36ky802atvO#ZZBvoI1V;P8&uTvrqboIz z!5t{fN-I$DZq32wv)7Ets+8?6`{9hcG=K0rQVY_1#U*F{;&F3|Q^>W}V6&q3xE{1a zWSJ*1-_$nA=WGbcv;BZc%?j;9vF9eVWU1)w;1nTxiDZ4SKK4D zy1}_V_ImN4=&W?j#?1mO3z8QYy35b(3bV6Epj^&dK06wi#YGTs6`0}@k89OC%M|_& z@2sgF8fG7OR1bl0YVI0J^7B^JJ4zpIs6wW}~2?FjQLE37ncL_1lJ=oZID zo+|EsAV}8{#kCu(qz7mr7NP)dQbHKxh!x|gN1rC3?g!L#F}N)XUMG!ztR(ol9DVk5 za{XZb3vk@2JkifgzocC5W>a)#s?JhrPbgnySniX(O9?Rt2}Z8W0pfg zp*|Syw8d+g03AoXn}rRM+V7=s=A+@W5iY)d)(E>v+M0UPEK@ugjAtl5=FYE zbf}IL!IOb$aYzB8B?lCfsxGF4LyhLbKvJbBZCP4s#1cGlGz|t8V3NG9VYIoA)`g%7Fu#FlJ094tv5&IIP5Q>Sn zjomB!>7xh1n+CaS3~+Pu1`hN}KFUz!@M_d!TV zEj1H4wV|@Dip+LrZbs2|u`&1MBsol^+WBcX$fx*m53GiT<*CYp?o^Chh|Uasv%)?yPbgSBd50M`m&ft;-~0*mrHh+M ziHU~?fE8lI***lhYd6DHkYi8q~U!WjhB*@*BdZQeiz#Wi_O1TD{T}y?on3@!5hWH7x;K- z^y#=I1|6dwz#qy=%Ug7mCTb2Bu+bO@H~yMw%CM+RmRTCninLMem}0Y>wrqI}E8Mqo zYx=H@7sh?x&RA`NI=O%0bm;>sj8WqCFFQ6BY6~g*?FU$-?SkD*4AYZKHHH9Bb*{2q z-C?_3miCCvSUXCN08Y@I;Vck^b_;g-oe@8I3OA$&q~%`{0FcpS<5>e z%Tet>UTyqrDyP1G|JJJ%PW^43JoSNfzhh>8T*N9GkTGUXwuQNs{HM!uY%2cBG&Dk~qBr9GUacA8wi#W&s~h5XzS|=X z(A_F0$iV~KDz>?GQ0gFgtu9ZvtRWumK27_e@~YsDCa!vF7HLUpZMaX~O|P7gKC{bQ z=G3aR-8O!N_zW=$cWebJ8oq@fO-f!!?FJu|G#r(*rvy^#f-d~;_zrO|KPQkb*4yK{vucdo zNfPNS9Nq9&OyKB$WZtd+Yb^|BGS_g+NmD0%ORI0h`E0j`PESDLqZWWmXBcV^5o%-I z&ZBd=v1zS2;zHj?KSOkQ*bhs+E4Qgf6aLXoM6u-!m*fP6_iAzEVBJQ##c1ZV>^uqAyPyb-!}^OZv;-?BwvZZFZD?ZVfZm0y!Dv-uh)<6RVpRKJ64 zb-#-6wM}+|1jphYV))ffwgb9JvFF~{I^S^06Rqhwf0OBb6il{5>J-9GKOhFdc1_|w zH%bR@s>eCD@ait2c5a0NOY)sF{seE1=vy@K35j@TMlz^Z`|A^xdr*3n^gD!i|7Ml^ z+n@1H9%EmRgX|kt`V$=VPLGF3cNjBbfmCCcQ)5`(IQD9R7($7(X}2nAi>Wyw_J(*Y z5Xd?6BR}D1xbQ#}8MxVf!rh6~cQa;HD(#Xhjy+G+R!GK{ zuKda^o;9X$v71zj$=VE%GL6o+U{x=??9a;>Hua+_fzD-B@pzxZQ8Uyy5T+-On867Y zYAfi18?Fv3pT|x}?+?H~n-Mm3jqKgO!#n%GD}%!S{e?;W-%ZIcM-vAT11AFs16yNj z6Ni6ao{E)t?T`f#yf0R}2el<25cq&dNXRgtV@pXlS2%>bvd!0U8=fR z@!x*Su_$JTbIGY^kq20z~Y2Wt7Z{ z@tWmDbYEgcj@R?|KEySc7~J5K4*=uW(L%MG)HarWp27Jk-|vU@E|V5rGaWdZ3x{a7Ti zY{l{9zpsyb&U&$^oI+7m6oChv7ZKyLi;=7JWAI+bD467Rg;L_Hwtj$~Ig_$VUAMs3 z@X$tM$wAczMeB>;Ql)P*6~Zlc1p#bj6G&%0Ct8t4F{<}9751O1;xuozdS&M?yR;6M zD0;BmR%%6>1@EAi?ExEn|DOWFbBz=S{2LdZCGy{y{QtXf{!=NM&|b<*Uq4^AiDa^N z_$W{yniQgWB$P*_hVB~cL_^IynmM+H=D;EgMP!s=H?o_;rH<3(94A?sOre>hjS7l= zvIg=m3NJo?ZTH$jZ5`XEem;GDPjWVk2+bq!?+!N|XWqJUPoBAdJP+-OGEDx^?9y(M z3b()zVm6Q0%7$Els`Ty&P160o3%*B)55+?l*TH#EKz#A2b&H4Ty62*62+B;nua05V^$~cabfZi4m{Cy_X#_1UL4Dh-$VoLD>HSBP358~uulw3 z2|bz}ZqWvNQSXp7@CMwwVDeF0xwgJK+IBApOVfn#(c4`++@V92hu^r|p+j3>`bwhR z*xz*pFZR1m4Ctc!w#8|_@wvZ7WWKb$`SiX1TKi@-cm_^%eVG z?Cd;~iH9;)zU?*b6Azt3+~iG*$xBP(H72s>A|H2?`sR7!ce?qxXZ_yC{i|PQuFC^_ zPz?U~EwTH95oS*O%FOsBXZ{&E(?|KF4_QO*#ATU;MJxj&R|dK9w?@+Q{BcCJ*2m{?RQ|7yN2A)+(6B3uJ&g|`P55o~X zw0J^3N8%b%bjW^mygm`4RO@SvC8%9NpM(`hywlxIT2|#oATMDF(3|8VSO>$)>I2Ba zDJ*aNv%0If4H1eR6j|Uz;M{eXK+Wpxa(i1>epQ>%FJU7`agTQQs|>V~`eo<irmK}K^;w6bn3{gTVRZn^k>bIi#EolLA~x~ptY zvZ~v!)#Y{2&hm)iCxi@-=?s)~bvBU=xMaJ|!*!5iL;{@qB@3wWu4R|^Y+6g%mB1b9 z+J0+Mqz6nl)*g%aE$kr2k?I0Cvh1gp7qQ~NHoZJqLk@8VY7r5NnxVJC1-SBDh>ELR z(a9Jq)lz_i3X|%;a{+8&!ap-D!DO4utMQ=7glN`|8xOkrt(%*hIg%^_%l?5UZ*dKw zlVifggc|*Ihap3U7zv+#OnA*Li}@CSOzVKLPI)S;IHJN$WBQv7ZyhTlv|wL*IcVn>~ z_Ci_4S(}5PE>A1+a#oZEwO@dKyI{c0V#Z5}VDQdo5Fg`JSK9z!eieiSR!b=HR&*U- z9il>%aqeHin;5lAqSkwwBMy%P>V>fF42Y-Xo#`F7}1@A zytTLlZs?<>W{`r}Dv(NA6rhom80-N%wkM^0wI4Dtp$hcS^-I@ApKJKHxvxH zv+yx^LHIBIv1ffD+{OWD88hThuB=nPLM_Bmekb|?MKh)np@GE=ZGSSgH+_Te@h+q#b{cA?C|{NO@%Esf@kOaKzMu>erBh|q_N$*%Z^zY}kDVY1@YkL^g%8M0oioBX*rMkstjS1M9W{{{@7w1MLFUSWY{JuCpkJLJ=pPu}j(pM}tGvKLq_}yo!(*{Vg;H__v41 zv4xIG_|uw|O!PpMLmO|O!5Y2g&^E-UtmcKm686QsS(TFxk%_(;j94NSosI!DaRCZP zF^zg$6l<|Zo#OgTy{+0NbO%wp+O5;z`@Rk#MtGRaKqg_C_GkN;?}=~Pr#$9%+@2m& zC*^<^#%X2a%-Die<2++|}j6bRPPV z2w|a+47W(wPkcu|V;&<)%xJ8lTja0VQngf83sqWKJ-2<JHo6k1n&J-5jt}#03mHmDVV!g){=8^wE=ao?zKT-NF^w!tt~q55{O~*!9-m z@}sJV))qD>Rn99ekO<5&9?(FC3#%ejlZzcm93_gf^k!9&2N}c0v;E3PvqdkH>}2wZ z(ZtN`=UAgGa>xR#_de_EWuwaOdSxBsw*8hRYBteBl}?!1X@H7w+mv?6tl^y{X~Qb3 zfHiC->0+=^BWbo+e1)UNAtqQp#D1qWnj@mO%@q<9?X+#UOf{^gY1Y5-EPq9pSCrBd znr8f2N2-W;79}cC94RJC)n_opYN+R!PfoCyWIIk9*5+Gakwf3(G$2X-qqb#!|m}IGBhh>KKMCN)=lW6ukd#quvV;Bf=g(sbsWp~Zd zt=fVnB;Rm?W>Hufe zG}9asYhE+ZT}G_6JVKPXqax0%;*t$Y+JYFUO004WRr`!-U8Ybc-CdK8x^Bu9^<9v$eX=KsaP1)zl0N#Q*P+ z-F*B!J$0|>AI=?@!~Bpw=bJUpF}eC1Ksn&03kJ2BssJ>_BWS;0z;oypCm zxjwVKIln#EW@>Zn(qM0*1s3sgzE7J@3|{U1axHk{xk8V@`PVV3$H5GR`znczjT+ia z8xdVhn0o>H=vsD5G|4nE#8nlc?mZ-`qTP7b*@~N_Q{UWsPVzcY2mPrJq~%(vVDgTT zRJ>3*t2>~1F-Hq>&0cR6{`oniVC$WVg1sN-Njm+}QPc8SbT%y`vF=bM)m7#}UXY<& zdbnDGrsCu1K0}uCB}#z6d<`vnNSNz}Aa~XU171`IeAj#8XIQHa=ZjRE z4NUZkLWe5hB*UKd6wnOkGlTGDz-3R7ep*h_OQfz!dFy%Ul5?-AARinO;H%`DVFk%? zJsaVQQB#XsQFTevooc@N7~VBo3WlwvzoSU@J9+qhOPXrVoRooM$IMgIOo!Cp=cX8zE8SL{ODSK%L4N zzVo!1<9G)@8~E@eVmfi=%oQ8)#dM3ouU>rIeG=f-=Jv$=%w<$^YFa);k|Fd&juB_G zx$uRQGS|jTr$%^zkFpBb2F57$`84T#mr(0<@kGYNIgMBnvq5mgvYcU!IymU_E0zP? zec%(#0HAW2e+9DP#CrI$B`ZV*u&%Gy7>r$JK9c0Q7m=?hxEjS?W?Xm%O!BI@rA4se z73~vmo^y+kj#yk8Q1uE~RPMYmMBl!_E3WA}OmwLFW&~O~7+HfJvtbEdv81R9byk`~ zRh4L-=dCre1s1er6dG4OaUf^l$NW)dTg1uYFcz3h^V4!+Fd{|iXyW5pA)db!dZURKl6n3dx zJD0fv)->c&EgE)JK4U~bws*#?16H8?l4CIMT5%2|E78an48~v&c$H;|mj*%qCKk6!hRT*0G}r7 zHNIFjO0(?Xh|i~Jxpn9t7kDP$&!Vg?wo>}CcaE>+A1lNZOJS!VDIOZ&cjE0=E%3jY zzeMqM|A;2uJn+jrGz{$Oa6AOV=sws$yitikFZRsuu>4_WB_u`jHDh{SEbaHoD55us zQ!xbgiq>7xpB|_o$kg{2tha0`NK1VAh^@4blTGe}3hRbRxG9X65Y$a`%{YX_3IrG2 zyI~OPdxy_F>{`!W-+hGk?`y?R6dhS23D&Wn&uA&@uUT!&?DPq09|9YT@f_2z|FI2x z>3--p(5$b!{1dqNI|wZF5j>9gC2$hl0_k3tmT4QvBMi-88zMkyn+x-R{|r{tDU-|t ziD(Ng35$iHV=O73`Yxw|G7PxVdgE5;IDxW8XFv-4ob!5)hPkHwzb$j_1 z-6E5MV~&&t7H)fJ9sm9yXapC*^&6@rIkBFFS%FYDwhrOG||Ko&!joKl3&m_CA-1-GI} zECgNfd32&e7NXQYLTnnbVR#~7l9}hpY=u7!z)RVh$W|a5$c@(UZ>;Q93@NOJ+-1#- zS1JdZ8tSRy7cWXpHo7Bmgi4N9OzMHi0@Q?B?s1jlaaHGWMyABXG-7h<(X*LKqL}+L z+yqI^FDXtzgBp2!RRfnKuw?i;7ylg0e4=hQ(0{QpgEh`X7&zir4K>n!r z0FLP;_>A9-?8r70T}xP)5H~XE5^a;oFg+VcT39T`PY$>$N>-sO%&>}R8(DQ>IgL;9 z$E8w|Ow8$mS@?>C`G5`$RxXAUtOVbp2wShg?w}7JYYuKybPluqSm`gx17##u_kRm3 zTw+Aj12c=DyEt@bOXE;&yFH+(f#LOJioFl3<=~fz?0)ZF^91?#6ouCVEnpK|>817f zQ=QO?2Fau57bdqz-`=esy4g5%UK+NT2ScwGD%OlNT++|nzcu&fxtUWw^o$1CnI!=o zu_ZV}7op^Qp9(xSDf)f%}nC$HmKHt6vH;=Cg#`dxp%E{t+sS_O#8 zf1d6Ba6j?TH4V5x-e&jCiBC--iu%kUN1)|aWIgl*yltIs zf?ixbdG;Wnr-^z?YR{=RWeboC?9^}>+;5LlA5XjmFgEEN`P5W@13Z-jAJ7q|mW$Ac zK6U|Wqm5YtXXK=ebQ@m6fZJc=5=xEWX!kHE)oej;l%U zQ*z9mE3@O~l(g%rQqO0aQe_7ali4$KbakqC=xV+*yX0dUaYQTDPf7b}ecz!f0ns)T-w^<(aASrF}t->_8+fv3oPg0-nYZsew)MO zXq9gYMXB@T?TcQ%Q`TK|)b?R;$d`o{Z&SDj z?-J7mFP)p7Qe^ zolY0ZQO=u{D`dUQCuO|U$xfN;guaYkv5coJImbfgsVa4*DXz15wxv@}&DO1NQTsB} z>eOJq)8}h=$~^ZNRNKKztXHG?jl_S<3e#D?Y2TwJJ(A+AE8iV{2JG)okdLsKzmBJP z9e2W9m0gP534SG_G&Z?&N0&6`Rf}FVo@8vhoWJbQkAZ;rnKT#a42x20et~NR;<`Ec z1LLQq!6WLExz}rW`|tz|z%jhg$O$) zf6ccUv=+H#=l^lDNa7p+<|TqZo<3LTm~eOTqK;5q!N4C8Pq~^0=f8XSkpI?wk4Lxr z2K3+kh*n;#QC;g+V9?W({X*@?#0@Pq$Cfu-Y3%%>=&F6j=;62JXMWB1O>S)Vn3J@c zuTSgC{8_t&w@m%nFS{!HS%AR2jojkG{nFPzf1g}_^o{YapQlTEC%K#!AfA+|-h4u) zbz_y&FD~|{8Tk>vg6nz}x>}!gmi$Py@?8DaV@mlM&!X(f2Sth3Q& ztu060*-0Lp_DSA_%C&xneuRY{cb~DxdE2~{<14;CyVN1~(OtO3Qh6IUPt}s%Wn0&u zo0Ol~ybqSUD;pbcCzJlT#L!} z^02sv-8AzCr=;4s)OMGn#W_*;p1)vMX^vd_MLyWR&{)4OG?IsHg`->Pu?=g=lqB-v zlMkO%AUH@_gqp%c7=N)Ra5NmFysf zd-cYZ(5Ckmr`5mJeDRrh_qEyUlH19va$B;+UU}?$>37ZhhFj~KaY5tHc!zR->pY%B z>-OWPz3b+&UU)T3V%7tZbh-30JN?wvrQ}y0)4bwSy|(e_`iMClNtc=P`qhfp{+}oF zo!a4H;;1ol%eT)uk=Fwl$z6v z{P?q#_gXf#=-xWAEopr8V7b|cE+fx{dpVO0^tagw`h8WA3RAE(x@0_2;bAiSSLbE6 z^;bX0r{~LP3%%p?O%0yI!)7q9_$j+ipl`j`p(9lq`?F_E)N-(HJiFn*dF_{FjtWPe z>n@4Dh;3^5y6bMPd*5jI z)xNAV)-dSNF|TxcX1gu_(u<9U*c?}^;!97qTN-fdl!kREN4l&KIiWgA<@v&sxf^np@JrQb9?=w>e+?xu1K_e(RI6jcC#J-8Jw+UsI>!fleRk zy~?gn9NeG8T?=aG?e$(FLajPVn&!Q-UAvLe=(Ho=B4cIlt%#QNGiuS|iS41YKkl~4 z?PHgi*gQ`CA_S9tPX*>s3XIu&xk4NFH|_aYAJTN=>kYnJy|t?Q>V4Y=>56x^cMMkL z!yfbid|5l6Xyit2AUl^X7B2FURM^R>utPz0%ap>(71ApYJ}`K;SR#I;W+xZ+F|3Tz_@x zaCP8o9bd`Y59-LDtFL`~Nz>ZPcY<%`x+fPt3OvZPITNDz{PM9khnyc@@M)`%7{__{ zq`PS5rn~kF6W&@zMrXX+}x;c*gg5EZ5yVm%sA8}?tCTF@*HQ- zJkDuRGY_!;Q0EIUu{PjWom#Elnj1gn~H;M=*8r|i~9w^BTp4u^Z-8kB;m75|~aQ@Zt zef2zC8?}#FN~&HvON%;HN}uw0S%(3O}=BU7=l&VeI8jgXQvz zO(l7n^Dj!z+Txxnbvi1U;B-E?Kqq**+q*geF)QvqHbV>`}IDGObOG zl4GeVXTQ0Arku0uGydeb2dgif6^I9O6x=Lpa(i~vw(PN_#)GBDm-=3^m(sn*m)(7T zFzM(qp7bjV;zc`BP^|LaW&fF!| z9d%8O>ucWy)Y1BVUg^1C?>g0d=v#5s&u8P4ckv(ia^gv$@`ukh5?40bG#;ZJdQ!8B z{Mko%)w%~&d-WF&?A#(ze|ocsZAkNu`I}c1#;v|kR^mA4h>hvJc%M?SUV=vSHbqUf zn5WbE9bC2sM=rWyXTDyJHYcxudO3lkE_nO51LruKXUNNa@xD{7>MrTKM^$^i?jrBd zh3{rmlT+9D-+whlb>4WLiDA|A3;Yd*E~OLfxL)5{(p?+*W@@V4{OYIj{anOv8n?Tz z2l=fj+B{`dyt#8&>#y$8l$`^o6>voG*P`j8DJn+3ilDz3TKX|A7qKM@AA1z!RFHzTI6~(r8_%clFqVlT=_2XWxm6&H#b)vD{K46{_WE}nJ4Pjhk$Y_Vg&xw%4&+yIz}mTS#xKOe?d$Ebm_EqZm`xAh`Y7p*Idn zkMtB{9_SwwsPrK}jIs@ox6`?36sP;*f_B{9nxzq`x^XE&GJQ3(PIte4y;Z7`dqBxD zPUwY^jr+jn>o89X*Ij1s7VtdTJZtwl_vq@i;$Tuc`T+%0Y=MDFr zN;$o^PmHWAxPp{Y)nzshUwD%2cPk-g?M$9O6-oE9& z`|EQ1x%UdT#Z8hw^57>IInwRgqVOwyN0ho+JmxlbHXF)#eoV9JRoy(8pDCiynDWt1 z>BnZ7td>57!BhPLWoxf1+pn9IAj@xjJk0VSpC zk{$gYVwCzlV+(X!GZb!WJ`|Ik>By` z>+J1auc+mRx=AII<*pgGo@}$eCBHI6ol^bP(mOxomelfzNyHS zSyIvzJ-C&(N!+q$T548w`&mMvrDoHy>a}vgNB}wmfxN zNEA82ZQ&fIZk-|dY~$V5ysy13`B!U$mcL#S>Lt=}?P<`Gg?SxuU5oV#_mS_nY?6=Q z(K_Z>k|lh|v2S_W`cI8}vaaf@EwW6^E67{*^r@}-G5-g%V@qR?Nw(&RE{X_Jzhc(v zQkW#pb@X{8RXV3$NJr@KXP0BeQP1YCj4XQ?{ZU(<%d9e|%l_hmGg~X89?x;KmdIYc zzHn{fMVg(ZBYDrNDO;zf=vf&EyM0MKqV0Hb>JA}_ZfQ$AzkYVSRNks7{G>U$r6tt| z^kY^eYsP9FQus2lRG#!-STYWsgYacmHj`f{+KW9+FA>&jQH zxpCT0&UM>6%C}5zF14um>R@GX)NYo^-75;6`jjwbzJz1N)5We%?@~?8`!#VzQK5s~ zvFhvtS*|iiD#O(mm9g_#MV#$2m{qn|Q?DS2|G?yXS{}!_SBI=9Uq`VKirD_}$??OT zFIvx^@Za_#&1BO=YK^=2UALL$86gW3j~#ZB_m`r1t2#7$Z5%L}EhjsnfbAKz?B-kn z<%@wL);rzf^OE=z#}|^1pR+8fmP&agK4oLYtW|g0f~W!?>$21>V>Nj#G55YyR>JKpTd}(5F76j^9GGpT8pV~f zNRTX*byy^lzuawC1x4cE4vDP&?_w>U2Pfp#@5GnK$FbWD z7CoNivd&Xsj>D|Xk_hh?C+be;-Sgx0I%={vVT)JI&bRvI9Qv7ZbyoFZ<@WAsO7KqX z1icqC%69FPx2ldKowSRoJh_(ou)VAH+Vek(NX`0CsoNRbUMF@v{#(6E<#9 z{v5T2F*KYgu9?r;w=X1)JuU<#w5^ zPet_R=mt!Epxapzy0Bi)IpWz;!m@X%oA#t_ZG1AbXX3*ba|{o;3XcmUE_n-Wma>RY`0X*FnPxQHo`3Lg}Am##Z*b#uIA&(CYO@G&8e}^KX=yI zw`7J%b?upEA&J(HE@`AkY6eCjS8g}7aIAVa?b#{qd!d69kF>h&-~ZkqVnO|l)SJ>_ zK^y0tjy12Gu}WxO^?={*EpOiI^%2%)eKd{_uO^1gdonPw|CHgCsw=d?1;kc0ntE%X zY-M;yzq8_5Q{Dx4cYOU-xtc9-UTx>DZ$}Jo&^D!gcbUC*e&v^x)e@DmyN%MQHJ=n; zid9aoX%MOOyC$e_8R8h_@^na&^Xek!d39)kyW_D#E$`B<-CPRU)AQ<7uh z5xc+@@jKY+ex%FaYTMD-KYO*3!~9x{Ps^OvEgY}RugY0{C-&IE&(C(QITpe5=An#& zfIvsT^*64f`_3&X(>_?(YC2!Ny>BqvnV);S>DF73?H=)aE2;h*v!kC37z~D$QagWG z?$&u-S%axin&Fs79D-UP`RcFY`B^18d`dmF|7kY1iL3W7p3lF_W@& zPqVs|6B}%8mUcNNet2kLxmYl+OunzJB`ddmp5o7t#=t{7Lb^6z)=zZV9nZft^~_Gr zsbars27CtzXRVwgY&f-4D>Y3WpWm6{cjK|Lc|SFNeOtJQsn+S&l;x3@)|HBT-zvxZ zecQ`#YutX?{%CC{*KQM@s_`4B*Dry?ri6&_2M&X zgiF2(E?YKZ-=|gWXHwSmzCJnWqsP;6@xDr`o;-ou*7)?_?3vXpRwe9rPy3~8a1&8t zHP;tTrwgr~sSf7^BDG^;lL8G(-#xUFc)LHd(W=X;EG6%Vz55{%Ejz_=t~I`T)88K0 z+7xl%;;Qb<PmXXNCc=AGHPrlB!A@=~5g$V5?#&cy3y z@2}|YB_)6BERZD|*`9nP__L{}^kh`3d|K0-R*`+MfzSqD4{w^X%n3J~60w5m0BNqk0l`L(M# zp|QK?NLs?Zq1V&~;;byT+ote8*wDgN#Nos5FoRvkkQD{YQHHRbqXUa+@izNP+32gTiAB}9sKz7}^b zDOEfheezJb8S&SAiul!capvo&gCwcc;TOjr;|Xp1K=Y<`L9z_e*5`3xl}+ z)i2wMX*~;i8?*cy4({T)S}na~iMi?Atg};TE5cHQ;`A@k_#_t@9Hp)F4c89qN!X)O zz997FrZs`rWK~y(u2xB$estE)w=HwaCD*Bb?KRy0XHG6@qA)BsEgPf@Eq+nY2arT+_Uf#9ljkv{|xUrHl@s6;dJ}oV_BlY_N zyN>jzfnB+pwk2KTGB->f*Uh$PQ_=~Tbo(^B3F7`=F9y>ikiH2#oRU} z*Jk8OubGlLuW0Usr@WmDCRvE@jtH5wrR~mw1Uu-xZM$c?0xg4lPnm3sEu35{8 zH@sq#O^^udW#emMBhgH+R{1;rgsuUguR0FV}L>3GrfItFd9cDX&zb zU5A#g@#&N|PMn_eDi;2bo_%}CgYn_71#;A7V)&a~nv*_otd&1M^XrCewrz47O)CP= zyhr}|*5IYWp1)>@tjU!OJRNvurcdxv zpK%`~+E1-Abd7K%{Iu(L4=FlvFsbSG)P1pAwvNl3a`fV7ic`&5&P5$je$w3&Pxx|f z|4z(Yd!$y&zu_2nf+|5$`PaA`=k&|Yv|l{qmr&($U-H!5vwQrH+G~DAqL zL;j^ocNM?v+2hKl6|ORsJMW~*-d)`OV>xyrm8uHMX(~#gWLB)aZ^|ByW z`8L_{)5NuI@zK%>R&Xfki>r}@%5--h+;09OBY8(nj(@u&nd?Da_pF~=bUG*hxIxy_ z{;*f)eu({EHr4GM3v&FAZdAE1Ilt}FFYyJpbf(@;BP34hyRM>bFH_4AZhTHUt)kPj zXVG4BY^s60`sw5}oG_R#i z3G|NX@A|%FOVZ8ijQ2l}X8Gvd3ZzCf);#j9T9n9pcH+F-#(w&DjiL`$XJumcDy3Q50j`yo5>CpK6xLYaG?@`jK7_GidKTa06dQAy`GoTa@ z)2qHNa8iI87xmTr+!Gb`UfiA^&0d+_79di1H?&H6EADup;UjGL{@#zQIcDE}O~@oo z?BAaMLXCLm&=sPrP*$>cxk15#>?d9CI%{v7H{W?`i|@)C-*)f*G-p#lrbA(vXxt*j zgOi`PKF-ZMSh#OcfA0c;M@5wzidA3wEPmU@UgXy6;n08jtKqs67nDN>Q&lg74j!4R zD%Zqid2{j)ze;X7(Vm>~Uv6|(cXt{~JpDQS=dBK3$)_)!7B5_oJ+&_*fSjEnHPt{Y zKy(7{)8IoBG*r53E+! zvIfrSKPD(uq)s+!+HgCfK~FpSp_FIw&K2K}svVTI?^lT3Z+j+zqnOYYetf+A<%X1s zqLhmH)?4RvrE2rW@8#nRO(AKATt4R~l|E1Fj6l0?`D+dNQv#1SWhb65oYAmVlT>)> zVT*(P58V@=xzn44wmi60^<%fgfkT{~8E4m<8teE@nB;Nx78o5*8wk>5{AU>qX$$iR*V;VfCNS zwg~iI`eZUgxssVKyjI+3McRvoej$E=qRj+WBnzG@*>C2i21%6+N=tDX^Ne zKdolc2M)vj>93}qF3t9Cd$XWw<4UXOhibB_a`V?;+?4NUQ(b4$JKsb5rfaC;HS+gj zo|TK7 z5A#)9iC>Ogjo#Ow>Ap(0@2c=_7dE9GO8W(*$lLQb6^a!FmxYw&-)Yg{+bZiVJ8%1w zw!3n1_8+Ylhvj=UAKh_m>Gr5J$2HIU9%jyo4>z6I=kl63r&lkM-A=M6Mt`U3;fpbf z!XFNAyJRByE~TMmry;Lz`mF5cee1riOW7-6GIwvBPvNB0!58_5^}Zdy<~UBke<8;k z&D?p5CY~y}pMUt4P28&M-+~wQ)%cfRD}A5#W2aw&#NJc)g9o=J_FmY`R}gC>KGFZ3 zx7Di@zKunjd$?zY81Hy)aAtd2`QkZsmjn(7CvCgYFSz=E@bh0UDunM_sui2H_pUD6 zdSvR1_Julak$bCNeeEH-mlY7#o*@WkwhrK&Yy8Gn%`g)hnDz=*QzAHhp zW;wZi#cjQ5J5=Z1j4JdIob&Lt{Gl9wnH#547x`DT$rQc1IYG;vKdUu^JbiC$+*ipN zuX9Y6sD73{a9qzz=H$+0 zU4<5Dy(*6d7w?!`X-b`%S3YBT;m12}c80MJa&&t_Ndm{4EFNUj)*UxZeI4cf?YB0{sUEa;Eo%L; z#opuH;=S`%u4StR zNhSrW`6)MO{1-}Y?z7_EI_2Y)gl!XFl~N9NHgYU+m#jJd-iWJ-ZS~%mnP+$0_GJ6H z$6lc+#AR2|LY}>4YpXI#`aN!jXTMoQTiL$nE1Uf@^N0v!5wH z7L}T#`E6BfT9I&;hSh5R#gT{9-%fjSU@tqzyoBW4>={=j*rx|N^qe{Lv%QX%xw=5x zX%<{gTdtwlAxTp(zB%#QUIpKibpRl@&C70#{B82Yv0|0D-U{`*%AR19@A zHB8N<4K)8jAP^4Hk^iA45D>WpU{c-e;O5jnoFjjO=PxJv4gKH0;Y{64c5)&z{mq$} z-`qv_o7PT5cXwN|6A6QXTKxCd;195+@%w|=)9ElAh`WgH)^21M8V2ML9mt|T7(Y4D0->ju<-8>a^QLzb{z`)V#3=8*&F&rGoClj5Z zsTjCmrq-MS_faxX9F0nK!b(ODC5lm+&S+3WPHRVJ2zpFx2Mc2vljcSu(TG-b-IpF6 zD{=j3=wusrPcqHgo~c5y_L&E@8%!1I;BL(n4jZ<%j|S&P!t){eb}zzMDrq!OcYBhP z6GlqG6m zO_>;-oKsahVeAW0L(&PX(FvBQK`ORobBU(Ee5M9hrXu+q^lli&xkt%_p97V4& zIW-n(@PVt?cz52-kAoTsuJBvnjREu{N91`&PbVkcXomw90YS=VKbjFhJ{cGrBa|)8jc4bX)R-y5aJwO0jIsZ!28Ot5M3|M~c3h-^b=mh6&B3LD zz+g)-kTYH~hD0$`jc9F;6AjQH$z8!`p#?Jb!56)|_UDrvklo50RGnl?rjU`r{&u&K zPKH#$7Uk~=U6pVVzF5m?zh+KhYVSdVI64v*SuVhK{QZ3(a=9(NZiMWT@0 zh%_n=E)q9oQeK4wjD6|g!%~0L0Y8%idS!tlTPgc{Y^1qLcN4azRE8^pAcA|vQK zQ6*3B02CTmu;IpfF%xJAk-wdoOk#kX_ejTkCiDz@15`3}mm3){K3gRNsvDr(G{b-0P41yYx^xMQYN^`($37}%Euk9y~ zhO0@m1|RljWW6H|TMn*oGMU_x@Cy5Wv8NCo+nH~c$ce&Icl zUcqI>%-~^Yq}UAwEPW~w*3s~V&uexcK&L14;eKUoi1ob71l@^bhd+Lyad9_ajq!ev zcs3{mi@BhJA*P14GjT{8BjrSKDs9`!D%AJTz=e%}9gi4eqN5#*wTp1|i=CXJ0doNu z5G(8FD#p0Gh)&?V49D*XqY!(DsTMF4VkZobYDULolFK0FPPtuPqXxqILxOl~ zf)C9YR46vXQw9bjxM4($T{) z9h2V!;z*HEKh8@yMZF6iQ4jHb;hz`*Ka&IY=#OKR)#+F>T+cY(k&<){e%}OCfYq(P z31hs!lLnOOj}&yM`z~(v@`A4G42Hv|1g@qm05dWhf(}2>qW*vfbO4#{dW;U_w=#h? z9onNo^O9k35lBX9R2obyEubUfWu%DAKwdVmd^&*;3yr{b!>!~okl`!IcFol+z4d0MKM6~Vak`RV134r3V{UnM@$6TX!LbSoGan+XUVXAbS+Mxv4adge&< zA*~3R_ojl&w8IxW0LYzT0iB^jG<8a4S3*3s0m;z=1Ajir0rStYgo`?orW-stg)euE zORm~F7z~j$(er(OKFI-T$*kd1DYQSilCFod3qH+{21ANBL;??R9PG44=^RTmf9IsI zfJbA{mQ#(>*(TaRDgp}#Vt*O}Ka&Hv(^(P9=0F?1;8;%6Nu>5&8R& z-wfTUjE}si@KdKQC?p)vu|5+xgCVjmYzmLkiCoNtZ?OYzD)^9 zm4R;XmA8=UVP{OXf-K?wOLkMT9fe5qaAROfHA2|3+Yl8aDfFhy6lR4AU*U$AoVGmz z#l(TavGcHe1E#13Bxfs)?2y@z9Bo#L|BJR2f!d2*tS{neaFkwVgB4x0IixWK%?yqf4msfzi zsT}n3N@uf#yBuE+JNc}?G^!8?vx4cnTV@_BxcI0w9$DYFgJyTbehpT;RehtNs=`(c zEUV+=THLa#NCw=w;0;SK{bASlQE(Zj#D$*i-rvAnXFynNx7aa$0;3^n*cH_NHGJbs zoRu(P$z9m0D6plMIF)M@aClAtC%z+RXgMHZrvjOFJFIqKhw5DAQ9v2Y!V&5_>-y82 zpofA<^igc3!6>MVH!BeE@n;8KD?y)V0&q2q)q+e$0sfn~z-A}a{hzh<;Z;w(ScC}I z=i9wk0Ya2`fN%f(BnK=u|34Ap+jy$y4s}h4t8;-;<1ZP?obGO9neJ~(hZ<_bWW+%& zw7DLq8w4Kk1S$`(X%%HNtCS-fgM#f$kt$zrnDh!hum>bs!l;>oFpxG^)$+UvM|M5smGRB&t7{VL4bHI|pSu#4623H=>IR z$p)ocf2i@>q>`t4_b7Ch*)Td|hyBJN7Rm5|xns{pghMNMA=pFg`1?r?xDquAu&(I_ zLr|0(EDw@xy&0tYNK?(r#ue-w(V?6bWK?3{ z=7Ba#@bS-yD_z(Gt1W#Hsj-U*b(JjOGb$oM>Na?(PF*{nK*-jjhxTn@0h-Zb4uZCq z%4CaxWckcY0zvw(1EQG5KAxTVpolt-5!8tg?Qn)KguSQMR`w=f?*}izuJ5(*uz(E< zEDYh1t8|i1JzoI{LL@{ntY^QUISRZ1k!Fu?#kad}T1|m~dkBh-v0>3+$ta+P9%%Z5 z59|NSK$0v}({Z%RxF#KS0v>R9~bwXEU83~NY7 z`1q3~-(8#x_%K@2%?__9j|Cqe-KS41whqwSK>9V9t~5=JHT0o{P&KNP6D*m-(8tKo z#qw5FFJO%QIAV;|(ELwC`0ZJAC3K4tECY(cQWUl;cxbakgAaQ&@*OQ5qJs2@9`<$T zD6qqmbbMG3^}=9fhy*i~=%wv+7!7u47##_VVp!wS1I}nqP!-}MHpsXHjRL!oj2C3k z9J=h@6|MyEkZSlY!g$K`2*#kWiGb%32=G=dRL_7nEQdq_8^u430%!=RjI$qv?asDd z!xp>^76<9DuSPQ$7FC;|eP_UT#@BA-u7`_LAUTnR^BxN@ig1i!ij5CvPVkV52e+CF z<1aQX*^tK+&dd#JVQrzh5-)zE`lg@r9*+|NC1k)C8<|#=F+rxO{FyN^$@7ttzg)h` z&I1cT1)vPbeExot1JcVG;={Mz{uz9+dZ_PYh-yT1gF^s#eFOF2 z>l4=12ZPyAXvXTHsB1JxnD^TZ)uy2*|L`SVEphaQJMs*GhkMulev$)X-;M@9EI1R_ zK=MoaYrK39c3c866T2L{t!GpMlG`5#v>?JU3D|tY**8WkpRaVty9W^nj!>M24M~Z; zqp;xXMWiVHfdc3RGCjJz42wM+jQqoh>O{7N5!~7XDxba4s*4*M4H?>2L1?AnrbBHAVm&n?U(2_-3-$SaxxnL_Y$aUK1Tcr#~5Pc z)^j6eTt5@slL08wfQXHn5mC(0kb?0`dQqs)&XAXP21Ie_23XX6(M(Y7G`w73jP}Br ziX+q$(nVEKFcoruwI}Sdhe8ZvRCFQhC@TGKJU&<+)X4+lVk7djWahwsB7*^u0<%t> zxfYW9oM-9yaM1Bf_+mp@G_0yK7@3%*mN%=FE60Jni$Pv&T0u%11<=F;_I;gk^ENbv z&9rLa>4ea78Ty9`#<}v&vxp4!)2If`04@avm4G>i&RdS`Cy4It)6&Mz;3u#)PdAhd zWU)x6W1~TVvVB;nW4Jc=;Q2=0QfSONU{b_1N+Xv=7M5DGarVkv8^A0mWMb!A)_E-Q z7*b6=tnGjASK5fgJU@`lQoPK0uI$24FWN z*c2u*chsQ+IvP$SbbtaMoFcnG7uk9mfMX{vy(>onXB=pXj}PQaLq53!R_L&~h!mum zOuN><3V*bQimpwas0>8ci@bc`BlNWxZu(?9Pla_B#`t_1QR}RA2!uOn^vh|znk?gw z)H;gqJy|=}d<3nJ1M#sj^XyT^&?w*eJ%%#MVk7Pu~wHDCtWjr_Kz z8|YwECO9G%xZ^l$zzi~)U;9fJ2mq)Lr~*4_RN11ie+{$&Ezn~}s;h7ul99i&l)fT(k7FV6+|WPw!zhal z0BR{?fFCJ4Qi;UnXZKsdusPs0%P?U$E`3yRa~jzRCO#y0M*gTg@x=OOKrbJG{vdM< z=nR~)si0SRHR#qMeqN}&cHJZ1vk980O;rx6gFK9$YUKHU+ad;CO@hM zllsHd7#nu?<}=22Az8y2c7|DFNcDw11|Tr(fY5n&^fkty-V|$lI7Eal0l=44rRQ}O zDm8louvk5a-(U!9Ms*}nP(ceCdeE^zeC%x@qC1yB-R8g|`a;>RTg9N=S3MpqCI1#1>#3EepY@3 zWu^nN6h@))OPQj=PV^|#rpxh-_4@$wG<>nv_mmk0nn3^{<&T><3#^Ye6R^8dYnCxY z{P+Dhx~8y3!+2X1dBc(LYq@YHkMIk=*!8hASr$3|EMeihu=>l=6^P(Fe6eHnqU9_S z3@4=c@Jk|gJi~{NmuC^4(IG>mp0BCJjxr$mB=DKl7=IC1!74nut;m|Ol29-@lmCmq z6o$LykRM^K5WkW!4P0C_w7`tY7u`tqB#Jx3Nnab`YSbd=^tC{OT_nq2H%0<|Dix|jE`(7%M2b@R)8i1V* zCvRYh$A}8(U|(cxB7=j?s6k0`Z=B?(5eVlYXkz0gmkBFGBfA+w%{cF6TnyqnL)^qx z67Gkheg*>(x>-xbon}I%;+{T6xL1!pOV|LaKRAV6+E6=IaPg(xvvxKu6O2lODTgSg z*DjziMP+a;1Cn$z>D*~FZCniN{MgCBR5#|Bkl#2CRRA&eLT%eUw>E)l6=1N#E@AE5 z#S~nP2p0iCRgH%`PNIjz?kzDXn+K}+1xm)c!#E%2$ipclzJe2WDui}}GMXmQk4$!Z zM?w9)V?%U;)lIl2h;hi$nQ{JE7;r?7SY}8)Fd7Fs%t2zJa}?TZKZ&-S0_UiKFLuvx z|6!*1>ZIWz6*fUAcABs&iLayHAScE9p!xNj^ivILFmrq=;}E-&cjp5?P|7t>3N{Y< z9AOIjdoc=zQhaIK)Ix5e!by1m$4=?gjxh&zcAjC*Nh>h($Inm6~ z(dp9PB^Qh;yY9&>C2j)ICyj_rYvM)+M?oB4B{z3|(>Dg8(J4@D!A|`t=D2@7n~4je z&e?dU^UidT`T}$#Y*h72V9Eeqr$b@vB~23XhoQoja2F)UcKR2oqv0|}<+XZhU;|-< z0%DDF1Un|H9trgz}p|O2&(FK;EhlXOteK96!-J9(YTLqFKG6#AkSP*)?)MAr ztzf$(@I36)XG-Jfm?WD~3^*VXMMOL6-Vi;oy} zJ*fg`>w*r4#n%4LRO;aZR;Jk0eL;dBpmQ`p=fDo%Hf&tX3^g9*!&(WrKIH(^x!kpt8jl~`9+d^%Q zvk2n_)pea`UCN*p0^pERe}WzSOb%Ge!!ka8kKCrpZ)^=>XFxy4`lB)*bLiiCXPESH z>goKI{nEDLAk$@nod5i;}!45AwW{rXkCu%99#J<@aw$CV_ z4-GhaC5ln^;yFywO|8Kf@%60yY0ES{=smCD+FeNu<})bnViKl?ixU_pk{-?y$Fe{b zOGb2iM|tMJLzS;g)qG7Nk^}0@2**Kitk5>Am}3v!A*%*A^5JX4B;&5ockqjx5$VCn zbu0igu^;M=D`$MHLi3opFeEI&=(av02}Ip4Y6H?%YrGiIfdxP zbnb-&k0|RFum-{Nr_fJhxVADy|5K8vPO^4FD^3g-7fYYo#G!5Ee29J6iPB9gmKb!< z4TD3MMB}W4qc%vlZT)ZwEL#S_1Upd*wPVV#(H`#WV?3p?UESnE1Id-Z4Y2|6up@I^ zC>|fhVQ4}LLT_QjISQ7=hHV`err4XDoz$r`V-FJEeWpkoWmo23j|QpvL27KD-|Ida zGFk_~-N;11dzwSD-9gRh`d_R%wt0;T%wzyY*snEGzMw+fAW#Wb9dmp}!-lIr>=<_+ zz9rPGEKtYM5$bs1I~p?6*!tq!J|C2>odRHNmw&WxG~nTL?+iy?Z_{zHa1fmUbp&)K zTo^bSG)ku!n(&duf=6+nVyGdf3#>CkMgwLD`b$Fo-2(va08j}`wEh$}8Yt}V;@&)m zd_p7RY75Fg1|U3%VsJU(&>NExcQgJ~(FpUjro-iS@UvLJ#io;PQ4BGy|2*CB`>_Rs zp*I&8hb!(cCpR=s|Uo=t@BqjDpN#{}T=K z0z|9pg;WJTxGw;VfeqvlaV*oBkX${;jIKmEo1wof74)_n{2sdvGAm=O3}}BJ_s%`! z27@0jm6d?jR)B%*F`5&|W|_$4&+{1QYF+T+KW>2x_D7TGPGgawt9Nbw{m&!qiKJ4k zp1j{4nyxYpN+mE-?ack3ONB2&?Sb((;T|vox`qXcHU55*1J)FbU4-A|t>$h{u+vN# zJ{Jcw1G1YpEcRJ@IN@L5hg5MWX!;~{>v})Pq54+}G-2YsK6W{NtA6O=3jB7j@>+Y| z4;%t6Y$51k_{wkm-}wG`0zR+!i*KdxAa2G?CJ+oUyt%jjH@wIL@wp4;dhwu9CJhqe z4H#~&(*M8>bUVNEUm<{H}thW5Mv`oD+w?Dg9vcy2W~xO91`(`=sT@zb`i+?;A@Hzg6-wlh4>EZt1cpUE-O6;N7prM#zh0vepbC$WjO<|l^K z!>>yXm0K{l3J{fzC2FMFhC^$v!53Re6aASLXuE$3;YZ4j2r`aG&qkM16G3(?fyWn? z2^bw`K?J)6IF40<^ytQ1?Cg$hfF%OFdQub{A68}wM1$1DkZofn7x=~yc=#c%Kc#v* zhW?6Ibc_f@G>*R3hY;fj*$sBT#=iSV1CdGoM;I=D^;e6jO)_E`*(|9OgRsQQJGas3qU-3kQlLp>VZIl=F& zV`~y=OiFBAk{pc#z;^~<`hi^{sGY;A`1p!p|LA$nGSvo7 zyV}4bYZMVpG6fF%d7F^XDzy<6>b~$P({|~dDR6@7>bLY84xzGRqr}H=Smx-W54PwB zg<bNT^jl&0*pm((ydVsT zp#}^<*i)ycUa)|T&U zV=cj)&?)9aNWzBHA8o90jB*0;fb0D>UU1rGAW{C~weT}Jz`SE@1b;6!8(Ox+R~cWy ztb>K1uE~q(Bkb+2F|pyp6N|Pk@C1vXau=-8E5EP?&-5Y)6kAV-gaxrpfm2OzC>Fbv z9`lnmis5G&@f#4Nv~wP+LPgUW>j_x%b$$-q7)m+pk2U=+W#bf(fuJvdPCK{@63l?~ewIjZQ5P@`8WX4TU zJvwiL%}AHqj!vLvPjq7#hdw12R>Q*=1V@0z4$4aQEI<#3Xq>YgNbGt2t5+-p+*hC% ztX(A?M#mn0jfJsN<`&j9goEUsz#xI~$CFN@qce`0T(8#be*(DjAhiqz*A4b`nfr^0 z22646m~^7)(#xg^!lfrZFmhqleavN4@S$yO{9}wr-4CWkenoQ@v?+k~lCOtH!#4G> zVzd;F`jA<}9A!1w%+5EX??c|9OrZZfv-$f(w!5^;@SZ;$4gB}5^oXI?^tPQLBn!6` z>5l+RNgD&h4qG<{BuGQg{alJpfOf=Sf{VQ;Bkw9hl7F6v9iA7VDVPq$#e)V4V|X@f z$-$M>9B`r^U=KZv6D8do6VnC{+FvS>-w)-$j-jImgHsNo{i}Q|Ao2PP3*~Du#Mg`d zGx5l9@u?KyF25-+S9&!^vEI@Ix> zi12Bg=6R`RffvIpg)XJ(_`)iUI@uX-)`;v<^~B(SB$z)HvP!JF+P;nj{k}x*> z{UisNP8$;sdX<*J(j4Nk&GRwX1~UuZt@P1MU2qIM_{!S3xpCkDM6*h01a{lEXC15H z8t~+l89bG!0;3K-OTP5U1(neI7eepHp2*~d;vEK=3!V89%Wycu=XlY7YXIeoe87X9 zB`q@?3kQS8vydemvL`2IgR-Kg(>FuZh*b*oVzV}r;bl(yx>;zsB?)>zwnK_pj)lXB z>f+&IK%#iyYs<&fOb%*i37XIptlg(>9}5k0yVsQNH7JBFrD@<@Si5ht8w(3FyVrze z>#BpoP=zYC8#=qP&hgKSwTwbCjeYv-9`G-8v605#&W@H8xM=^0$AAi_&$NjY8{Cy7 zd*Mu$LSMZ{T!KyF;@IQ2Vv`~%%;uZ-zAYUfxd7`g~d9m*Z4cEeZP zGhjPd?J9@PM4{;vHh@0MV402TMjDPexHrY1M)fIIZb5hGphl@<8s(e)UuZ^;1|o@< zUCx0Ql)#2K*42da{sSYvGu#bXDwYII5{IyZ4LJg^!pT}cHSivKSswOR@lN;zgYqQD zpRnHvxj+TX1+h)xyFCULHxgW}0h3<*rYw$prbvXQ7(!FzF&4U8#wrOcGc(C*%QkbS z#sYE$e6gl&@)NMy|B}>Z{sGj*h~JDi4S!XM(QeevQ5naB6JCuCYb-vCpq8=`+p<) zLyN!6h}`Y*uL3VONZQcd;8?GI!}*^$@pZ`VD=tL@FPH&?wDzBN!O!G?+-a=Rz&aO+ zh9ZEBiWM9#hc~~~NKQ@~aJezwia3fqyjg==I>7&K!RX+DVfCCjc2-@pKOsm2-3V?* zMSnLX{l4ga$g;o3s-b`X`!5W$J|yC8P5TY#hA=Y3`kfdNduRRs6mg`PkTlZQmK;Mj z^26DFf*D4dm%{%iY5uBiG?Q%@NG0@vKCD3>78nVX7yj=gFoCDOp&Sh-sX$uD%RI3k zT{%gC^%!N03~5XLFEWhOIqHE1I}awvf|CkE&&TE#0#ajV`>SXM12SR^sEnF}CO5&L zX9G<8(xv~ej7%P^MAUni8ubc7LpOkWvDD*b|5wxu28!B)dW~t&YP2wkr4C&FzoN#u ztPiz%X_Wik3!v;ANKW)H3Xg@$OjygaXn&(0*2KRRj_+G*oT&SyA-dPY>KHcl%2ynP zm~7)dbofmMl_(5d-GkR%Q0tb@Sx!WCBk;B^U3Xcj&MFC7C{cw15)pVL-3cBK#(!=B zbxv)CpUxUEKvE{tkN0ym$I3QRX^0_UT>p(yXb&$q3RY>C3|M8*u^D;?#fV5|5M#cV zca$E5nZ5^XzhP&2RU23(K~qWmCQu9HK4!o&jEn?*%93r*D!S>A`Ttf#;1hk%t7V@9 zt4hlk(bwT!@EwK7!QEPhaSJxODhc|-K7}~60GkF2M2rFq7v>D*zwR=lZ1^GP4GLK$ z!w+#@9&CY~0=+*o3Xi)zq#w{dhE^vSFO4CWs+PDg33UPXu=bVP<&NU!xpI&++>MoxGVrKlSj?i zSZ#8G9ro4-oatBbuM~{|9>34c;U`@|GdFbWF4hWMeJp_w-+0JiNezkrG8bL2X@IQp=qO^R0UV^kX%j;D6-9Zy0+f zK?>bmhIW9ly;^7?OGHeUu2ECw_nkL-3o&CEq@38rgtMZoGYr?a44oFlZ^(w$iO*Xg zJlR8Iu-%|lVyrYw&LyE15gYn={N}+{whDbQ(|jqGsqkB&B$gtK%JuGn!mumxo%$?6 z81GSe=$2ptZj}`a z;3Gj%A>TY5PCn$DZ^1WV3i0=o9MEDn8tCwaOe1m8Gfhql_kaEXNyS0f%)r*Rv^X%u zB||Yy9SrBwd8PI_%s;+I%;Ztnj&(@>bs)fEJku(+@#DA!Fb&#=r9n z>8!8&Obr`2(+U{mwEtQiln4z@T)LKA=#}jExcBQn~COLwLX|Bq1xohTjLT z#)gkyu#Vcm=Biw=T!=t;0I?UFE=ax|8wZ3i{DNdeLt8{m(}z%i?he+#80QiPFQd5t zijCMVI}|D1X(Inv2JHgiYcHmJiRh_?u+F%VUVAoNW2eODXy|+|*aA&@2dgAl3z;n) z8wcaw#Pis?Lm#5gbT#?`GFWbG9K$h{v5_nv?VnKyy{89aD|VA@*@m$(p(kq@TuOpQ z;+>U+`|F?pqD_Rp^j*W08PSk4{0#{sO@gpRBZcR-z`$T4MnC8{T91m&AgCc+vkj{G zLJ%?wU@ipEe?Q3q(X>%0jO?J|-b<$f?0WM(Hyz z1z!wA!tizrq9}Ix@&@nd@Xk(X`x(xJIzc@bUWSQU(A4`i@d!{{A3>2gb*vN&R!_t# zjQVW>{ywA!*jDVH{{Kd*6*xvsR#x;Km;&_0J`7*jh>>cA3HDrT`cc;^3}{6>h84;Z zq*{SxlQ$?XPKaz+Zviy^J20S7JC0{0NwfmHA2_xJ?*y$41n%)gtN24@h_(Q>JP>;= z4D!e3gY7Dy^UjNag&b-P8K6kCH3W+M8Jsg!{efNy1$xCCr8HWvM!FqXnwKDtu&MKi z*#aB1QNY3pb+j~Cn`le$)GuZck#ipa(^Mg_2m#jgZ~(l57Mo3kgzuK=XG5 zgboF6R08clz`N=}uDsiw5m<)LaX~L>70rmX5PQ;!d-3nW7N7@y0x@dZ%?TpLWZ-B) zGVsEMe4GVU)@q65r@+jS2JBe6!9xmE{S*e1Wn%Q8-2=FE$yuroH#(CQh*bp}Y j`Utgn-xWrZov<)t1v(yBTQJ^Xyt)y1+D#s?&B6cxGUBGv literal 0 HcmV?d00001 diff --git a/lib/jshint.js b/lib/jshint.js new file mode 100644 index 00000000..ad26a8cc --- /dev/null +++ b/lib/jshint.js @@ -0,0 +1,3963 @@ +/* + * JSHint, by JSHint Community. + * + * Licensed under the same slightly modified MIT license that JSLint is. + * It stops evil-doers everywhere. + * + * JSHint is a derivative work of JSLint: + * + * Copyright (c) 2002 Douglas Crockford (www.JSLint.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * The Software shall be used for Good, not Evil. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * JSHint was forked from 2010-12-16 edition of JSLint. + * + */ + +/* + JSHINT is a global function. It takes two parameters. + + var myResult = JSHINT(source, option); + + The first parameter is either a string or an array of strings. If it is a + string, it will be split on '\n' or '\r'. If it is an array of strings, it + is assumed that each string represents one line. The source can be a + JavaScript text or a JSON text. + + The second parameter is an optional object of options which control the + operation of JSHINT. Most of the options are booleans: They are all + optional and have a default value of false. One of the options, predef, + can be an array of names, which will be used to declare global variables, + or an object whose keys are used as global names, with a boolean value + that determines if they are assignable. + + If it checks out, JSHINT returns true. Otherwise, it returns false. + + If false, you can inspect JSHINT.errors to find out the problems. + JSHINT.errors is an array of objects containing these members: + + { + line : The line (relative to 0) at which the lint was found + character : The character (relative to 0) at which the lint was found + reason : The problem + evidence : The text line in which the problem occurred + raw : The raw message before the details were inserted + a : The first detail + b : The second detail + c : The third detail + d : The fourth detail + } + + If a fatal error was found, a null will be the last element of the + JSHINT.errors array. + + You can request a Function Report, which shows all of the functions + and the parameters and vars that they use. This can be used to find + implied global variables and other problems. The report is in HTML and + can be inserted in an HTML . + + var myReport = JSHINT.report(limited); + + If limited is true, then the report will be limited to only errors. + + You can request a data structure which contains JSHint's results. + + var myData = JSHINT.data(); + + It returns a structure with this form: + + { + errors: [ + { + line: NUMBER, + character: NUMBER, + reason: STRING, + evidence: STRING + } + ], + functions: [ + name: STRING, + line: NUMBER, + last: NUMBER, + param: [ + STRING + ], + closure: [ + STRING + ], + var: [ + STRING + ], + exception: [ + STRING + ], + outer: [ + STRING + ], + unused: [ + STRING + ], + global: [ + STRING + ], + label: [ + STRING + ] + ], + globals: [ + STRING + ], + member: { + STRING: NUMBER + }, + unuseds: [ + { + name: STRING, + line: NUMBER + } + ], + implieds: [ + { + name: STRING, + line: NUMBER + } + ], + urls: [ + STRING + ], + json: BOOLEAN + } + + Empty arrays will not be included. + +*/ + +/*jshint + evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true +*/ + +/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", + "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", + "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", + "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", + "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, + __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, + Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, + CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, + Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag, + E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, + Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, + FormField, Frame, Function, Fx, GetObject, Group, Hash, HotKey, HTMLElement, + HtmlTable, Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, + Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, + MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native, + NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI, + POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError, + Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, + SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, + ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, + Slick, Slider, Selector, String, Style, SyntaxError, Sortable, Sortables, + SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, + Timer, Tips, Type, TypeError, Toggle, Try, URI, URIError, URL, VBArray, WSH, + WScript, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, XPathException, + XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a, + addEventListener, address, alert, apply, applicationCache, arguments, arity, + asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee, + caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, + close, closed, closure, comment, condition, confirm, console, constructor, + content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, + decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, + dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent, + entityify, eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil, + ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, + forin, fragment, frames, from, fromCharCode, fud, funct, function, functions, + g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict, + hasOwnProperty, help, history, i, id, + identifier, immed, implieds, include, indent, indexOf, init, ins, instanceOf, + isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, join, jshint, + JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, + latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, + log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, + moveTo, mootools, name, navigator, new, newcap, noarg, node, noempty, nomen, + nonew, nud, onbeforeunload, onblur, onerror, onevar, onfocus, onload, onresize, + onunload, open, openDatabase, openURL, opener, opera, outer, param, parent, + parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, + prototype, prototypejs, push, quit, range, raw, reach, reason, regexp, + readFile, readUrl, regexdash, removeEventListener, replace, report, require, + reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, + runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, send, + serialize, setInterval, setTimeout, shift, slice, sort,spawn, split, stack, + status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, + test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type, + typeOf, Uint16Array, Uint32Array, Uint8Array, undef, unused, urls, value, valueOf, + var, version, WebSocket, white, window, Worker, wsh*/ + +/*global exports: false */ + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSHINT function itself. + +var JSHINT = (function () { + "use strict"; + + var anonname, // The guessed name for anonymous functions. + +// These are operators that should not be used with the ! operator. + + bang = { + '<' : true, + '<=' : true, + '==' : true, + '===': true, + '!==': true, + '!=' : true, + '>' : true, + '>=' : true, + '+' : true, + '-' : true, + '*' : true, + '/' : true, + '%' : true + }, + +// These are the JSHint boolean options. + + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + bitwise : true, // if bitwise operators should not be allowed + boss : true, // if advanced usage of assignments should be allowed + browser : true, // if the standard browser globals should be predefined + couch : true, // if CouchDB globals should be predefined + curly : true, // if curly braces around blocks should be required (even in if/for/while) + debug : true, // if debugger statements should be allowed + devel : true, // if logging globals should be predefined (console, alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es5 : true, // if ES5 syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + jquery : true, // if jQuery globals should be predefined + latedef : true, // if the use before definition should not be tolerated + laxbreak : true, // if line breaks should not be checked + loopfunc : true, // if functions should be allowed to be defined within loops + mootools : true, // if MooTools globals should be predefined + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be disallowed + node : true, // if the Node.js environment globals should be predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be allowed + passfail : true, // if the scan should stop on first error + plusplus : true, // if increment/decrement should not be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be predefined + regexdash : true, // if unescaped last dash (-) inside brackets should be tolerated + regexp : true, // if the . should not be allowed in regexp literals + rhino : true, // if the Rhino environment globals should be predefined + undef : true, // if variables should be declared before used + scripturl : true, // if script-targeted URLs should be tolerated + shadow : true, // if variable shadowing should be tolerated + strict : true, // require the "use strict"; pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` should be tolerated + trailing : true, // if trailing whitespace rules apply + white : true, // if strict whitespace rules apply + wsh : true // if the Windows Scripting Host environment globals should be predefined + }, + +// browser contains a set of global names which are commonly provided by a +// web browser environment. + + browser = { + ArrayBuffer : false, + ArrayBufferView : false, + addEventListener: false, + applicationCache: false, + blur : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + DataView : false, + defaultStatus : false, + document : false, + event : false, + FileReader : false, + Float32Array : false, + Float64Array : false, + focus : false, + frames : false, + getComputedStyle: false, + HTMLElement : false, + history : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Image : false, + length : false, + localStorage : false, + location : false, + moveBy : false, + moveTo : false, + name : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener: false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + setInterval : false, + setTimeout : false, + status : false, + top : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false + }, + + couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false + }, + + devel = { + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false + }, + + escapes = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '/' : '\\/', + '\\': '\\\\' + }, + + funct, // The current function + + functionicity = [ + 'closure', 'exception', 'global', 'label', + 'outer', 'unused', 'var' + ], + + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + jsonmode, + + jquery = { + '$' : false, + jQuery : false + }, + + lines, + lookahead, + member, + membersOnly, + + mootools = { + '$' : false, + '$$' : false, + Assets : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator : false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false + }, + + nexttoken, + + node = { + __filename : false, + __dirname : false, + exports : false, + Buffer : false, + GLOBAL : false, + global : false, + module : false, + process : false, + require : false + }, + + noreach, + option, + predefined, // Global variables defined by option + prereg, + prevtoken, + + prototypejs = { + '$' : false, + '$$' : false, + '$A' : false, + '$F' : false, + '$H' : false, + '$R' : false, + '$break' : false, + '$continue' : false, + '$w' : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false + }, + + rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + java : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false + }, + + scope, // The current scope + src, + stack, + +// standard contains the global names that are provided by the +// ECMAScript standard. + + standard = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + 'eval' : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Math : false, + Number : false, + Object : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false + }, + + standard_member = { + E : true, + LN2 : true, + LN10 : true, + LOG2E : true, + LOG10E : true, + MAX_VALUE : true, + MIN_VALUE : true, + NEGATIVE_INFINITY : true, + PI : true, + POSITIVE_INFINITY : true, + SQRT1_2 : true, + SQRT2 : true + }, + + strict_mode, + syntax = {}, + tab, + token, + urls, + warnings, + + wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true + }, + +// Regular expressions. Some of these are stupidly long. + +// unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i, +// unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, +// token + tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/, +// characters in strings that need escapement + nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, + nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, +// star slash + lx = /\*\/|\/\*/, +// identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/, +// javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i, +// catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + + function F() {} // Used by Object.create + + function is_own(object, name) { + +// The object.hasOwnProperty method fails when the property under consideration +// is named 'hasOwnProperty'. So we have to use this more convoluted form. + + return Object.prototype.hasOwnProperty.call(object, name); + } + +// Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== 'function') { + Array.isArray = function (o) { + return Object.prototype.toString.apply(o) === '[object Array]'; + }; + } + + if (typeof Object.create !== 'function') { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== 'function') { + Object.keys = function (o) { + var a = [], k; + for (k in o) { + if (is_own(o, k)) { + a.push(k); + } + } + return a; + }; + } + +// Non standard methods + + if (typeof String.prototype.entityify !== 'function') { + String.prototype.entityify = function () { + return this + .replace(/&/g, '&') + .replace(//g, '>'); + }; + } + + if (typeof String.prototype.isAlpha !== 'function') { + String.prototype.isAlpha = function () { + return (this >= 'a' && this <= 'z\uffff') || + (this >= 'A' && this <= 'Z\uffff'); + }; + } + + if (typeof String.prototype.isDigit !== 'function') { + String.prototype.isDigit = function () { + return (this >= '0' && this <= '9'); + }; + } + + if (typeof String.prototype.supplant !== 'function') { + String.prototype.supplant = function (o) { + return this.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = o[b]; + return typeof r === 'string' || typeof r === 'number' ? r : a; + }); + }; + } + + if (typeof String.prototype.name !== 'function') { + String.prototype.name = function () { + +// If the string looks like an identifier, then we can return it as is. +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can simply slap some quotes around it. +// Otherwise we must also replace the offending characters with safe +// sequences. + + if (ix.test(this)) { + return this; + } + if (nx.test(this)) { + return '"' + this.replace(nxg, function (a) { + var c = escapes[a]; + if (c) { + return c; + } + return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); + }) + '"'; + } + return '"' + this + '"'; + }; + } + + + function combine(t, o) { + var n; + for (n in o) { + if (is_own(o, n)) { + t[n] = o[n]; + } + } + } + + function assume() { + if (option.couch) + combine(predefined, couch); + + if (option.rhino) + combine(predefined, rhino); + + if (option.prototypejs) + combine(predefined, prototypejs); + + if (option.node) + combine(predefined, node); + + if (option.devel) + combine(predefined, devel); + + if (option.dojo) + combine(predefined, dojo); + + if (option.browser) + combine(predefined, browser); + + if (option.jquery) + combine(predefined, jquery); + + if (option.mootools) + combine(predefined, mootools); + + if (option.wsh) + combine(predefined, wsh); + + if (option.globalstrict && option.strict !== false) + option.strict = true; + } + + +// Produce an error warning. + + function quit(message, line, chr) { + var percentage = Math.floor((line / lines.length) * 100); + + throw { + name: 'JSHintError', + line: line, + character: chr, + message: message + " (" + percentage + "% scanned)." + }; + } + + function warning(m, t, a, b, c, d) { + var ch, l, w; + t = t || nexttoken; + if (t.id === '(end)') { // `~ + t = token; + } + l = t.line || 0; + ch = t.from || 0; + w = { + id: '(error)', + raw: m, + evidence: lines[l - 1] || '', + line: l, + character: ch, + a: a, + b: b, + c: c, + d: d + }; + w.reason = m.supplant(w); + JSHINT.errors.push(w); + if (option.passfail) { + quit('Stopping. ', l, ch); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit("Too many errors.", l, ch); + } + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + var w = warning(m, t, a, b, c, d); + quit("Stopping, unable to continue.", w.line, w.character); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + + + +// lexical analysis and token construction + + var lex = (function lex() { + var character, from, line, s; + +// Private lex methods + + function nextLine() { + var at, + tw; // trailing whitespace check + + if (line >= lines.length) + return false; + + character = 1; + s = lines[line]; + line += 1; + at = s.search(/ \t/); + + if (at >= 0) + warningAt("Mixed spaces and tabs.", line, at + 1); + + s = s.replace(/\t/g, tab); + at = s.search(cx); + + if (at >= 0) + warningAt("Unsafe character.", line, at); + + if (option.maxlen && option.maxlen < s.length) + warningAt("Line too long.", line, s.length); + + // Check for trailing whitespaces + tw = s.search(/\s+$/); + if (option.trailing && ~tw && !~s.search(/^\s+$/)) + warningAt("Trailing whitespace.", line, tw); + + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var i, t; + if (type === '(color)' || type === '(range)') { + t = {type: type}; + } else if (type === '(punctuator)' || + (type === '(identifier)' && is_own(syntax, value))) { + t = syntax[value] || syntax['(error)']; + } else { + t = syntax[type]; + } + t = Object.create(t); + if (type === '(string)' || type === '(range)') { + if (!option.scripturl && jx.test(value)) { + warningAt("Script URL.", line, from); + } + } + if (type === '(identifier)') { + t.identifier = true; + if (value === '__iterator__' || value === '__proto__') { + errorAt("Reserved name '{a}'.", + line, from, value); + } else if (option.nomen && + (value.charAt(0) === '_' || + value.charAt(value.length - 1) === '_')) { + warningAt("Unexpected {a} in '{b}'.", line, from, + "dangling '_'", value); + } + } + t.value = value; + t.line = line; + t.character = character; + t.from = from; + i = t.id; + if (i !== '(endline)') { + prereg = i && + (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || + i === 'return'); + } + return t; + } + +// Public lex methods + + return { + init: function (source) { + if (typeof source === 'string') { + lines = source + .replace(/\r\n/g, '\n') + .replace(/\r/g, '\n') + .split('\n'); + } else { + lines = source; + } + + // If the first line is a shebang (#!), make it a blank and move on. + // Shebangs are used by Node scripts. + if (lines[0] && lines[0].substr(0, 2) == '#!') + lines[0] = ''; + + line = 0; + nextLine(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ''; + from = character; + if (s.charAt(0) !== begin) { + errorAt("Expected '{a}' and instead saw '{b}'.", + line, character, begin, s.charAt(0)); + } + for (;;) { + s = s.slice(1); + character += 1; + c = s.charAt(0); + switch (c) { + case '': + errorAt("Missing '{a}'.", line, character, c); + break; + case end: + s = s.slice(1); + character += 1; + return it('(range)', value); + case '\\': + warningAt("Unexpected '{a}'.", line, character, c); + } + value += c; + } + + }, + +// token -- this is called by advance to get the next token. + + token: function () { + var b, c, captures, d, depth, high, i, l, low, q, t; + + function match(x) { + var r = x.exec(s), r1; + if (r) { + l = r[0].length; + r1 = r[1]; + c = r1.charAt(0); + s = s.substr(l); + from = character + l - r1.length; + character += l; + return r1; + } + } + + function string(x) { + var c, j, r = ''; + + if (jsonmode && x !== '"') { + warningAt("Strings must use doublequote.", + line, character); + } + + function esc(n) { + var i = parseInt(s.substr(j + 1, n), 16); + j += n; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warningAt("Unnecessary escapement.", line, character); + } + character += n; + c = String.fromCharCode(i); + } + j = 0; + for (;;) { + while (j >= s.length) { + j = 0; + if (!nextLine()) { + errorAt("Unclosed string.", line, from); + } + } + c = s.charAt(j); + if (c === x) { + character += 1; + s = s.substr(j + 1); + return it('(string)', r, x); + } + if (c < ' ') { + if (c === '\n' || c === '\r') { + break; + } + warningAt("Control character in string: {a}.", + line, character + j, s.slice(0, j)); + } else if (c === '\\') { + j += 1; + character += 1; + c = s.charAt(j); + switch (c) { + case '\\': + case '"': + case '/': + break; + case '\'': + if (jsonmode) { + warningAt("Avoid \\'.", line, character); + } + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'u': + esc(4); + break; + case 'v': + if (jsonmode) { + warningAt("Avoid \\v.", line, character); + } + c = '\v'; + break; + case 'x': + if (jsonmode) { + warningAt("Avoid \\x-.", line, character); + } + esc(2); + break; + default: + warningAt("Bad escapement.", line, character); + } + } + r += c; + character += 1; + j += 1; + } + } + + for (;;) { + if (!s) { + return it(nextLine() ? '(endline)' : '(end)', ''); + } + t = match(tx); + if (!t) { + t = ''; + c = ''; + while (s && s < '!') { + s = s.substr(1); + } + if (s) { + errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); + } + } else { + + // identifier + + if (c.isAlpha() || c === '_' || c === '$') { + return it('(identifier)', t); + } + + // number + + if (c.isDigit()) { + if (!isFinite(Number(t))) { + warningAt("Bad number '{a}'.", + line, character, t); + } + if (s.substr(0, 1).isAlpha()) { + warningAt("Missing space after '{a}'.", + line, character, t); + } + if (c === '0') { + d = t.substr(1, 1); + if (d.isDigit()) { + if (token.id !== '.') { + warningAt("Don't use extra leading zeros '{a}'.", + line, character, t); + } + } else if (jsonmode && (d === 'x' || d === 'X')) { + warningAt("Avoid 0x-. '{a}'.", + line, character, t); + } + } + if (t.substr(t.length - 1) === '.') { + warningAt( +"A trailing decimal point can be confused with a dot '{a}'.", line, character, t); + } + return it('(number)', t); + } + switch (t) { + + // string + + case '"': + case "'": + return string(t); + + // // comment + + case '//': + if (src) { + warningAt("Unexpected comment.", line, character); + } + s = ''; + token.comment = true; + break; + + // /* comment + + case '/*': + if (src) { + warningAt("Unexpected comment.", line, character); + } + for (;;) { + i = s.search(lx); + if (i >= 0) { + break; + } + if (!nextLine()) { + errorAt("Unclosed comment.", line, character); + } + } + character += i + 2; + if (s.substr(i, 1) === '/') { + errorAt("Nested comment.", line, character); + } + s = s.substr(i + 2); + token.comment = true; + break; + + // /*members /*jshint /*global + + case '/*members': + case '/*member': + case '/*jshint': + case '/*jslint': + case '/*global': + case '*/': + return { + value: t, + type: 'special', + line: line, + character: character, + from: from + }; + + case '': + break; + // / + case '/': + if (token.id === '/=') { + errorAt( +"A regular expression literal can be confused with '/='.", line, from); + } + if (prereg) { + depth = 0; + captures = 0; + l = 0; + for (;;) { + b = true; + c = s.charAt(l); + l += 1; + switch (c) { + case '': + errorAt("Unclosed regular expression.", + line, from); + return; + case '/': + if (depth > 0) { + warningAt("Unescaped '{a}'.", + line, from + l, '/'); + } + c = s.substr(0, l - 1); + q = { + g: true, + i: true, + m: true + }; + while (q[s.charAt(l)] === true) { + q[s.charAt(l)] = false; + l += 1; + } + character += l; + s = s.substr(l); + q = s.charAt(0); + if (q === '/' || q === '*') { + errorAt("Confusing regular expression.", + line, from); + } + return it('(regexp)', c); + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + break; + case '(': + depth += 1; + b = false; + if (s.charAt(l) === '?') { + l += 1; + switch (s.charAt(l)) { + case ':': + case '=': + case '!': + l += 1; + break; + default: + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); + } + } else { + captures += 1; + } + break; + case '|': + b = false; + break; + case ')': + if (depth === 0) { + warningAt("Unescaped '{a}'.", + line, from + l, ')'); + } else { + depth -= 1; + } + break; + case ' ': + q = 1; + while (s.charAt(l) === ' ') { + l += 1; + q += 1; + } + if (q > 1) { + warningAt( +"Spaces are hard to count. Use {{a}}.", line, from + l, q); + } + break; + case '[': + c = s.charAt(l); + if (c === '^') { + l += 1; + if (option.regexp) { + warningAt("Insecure '{a}'.", + line, from + l, c); + } else if (s.charAt(l) === ']') { + errorAt("Unescaped '{a}'.", + line, from + l, '^'); + } + } + q = false; + if (c === ']') { + warningAt("Empty class.", line, + from + l - 1); + q = true; + } +klass: do { + c = s.charAt(l); + l += 1; + switch (c) { + case '[': + case '^': + warningAt("Unescaped '{a}'.", + line, from + l, c); + q = true; + break; + case '-': + if (q) { + q = false; + } else { + warningAt("Unescaped '{a}'.", + line, from + l, '-'); + q = true; + } + break; + case ']': + if (!q && !option.regexdash) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, '-'); + } + break klass; + case '\\': + c = s.charAt(l); + if (c < ' ') { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === '<') { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + q = true; + break; + case '/': + warningAt("Unescaped '{a}'.", + line, from + l - 1, '/'); + q = true; + break; + case '<': + q = true; + break; + default: + q = true; + } + } while (c); + break; + case '.': + if (option.regexp) { + warningAt("Insecure '{a}'.", line, + from + l, c); + } + break; + case ']': + case '?': + case '{': + case '}': + case '+': + case '*': + warningAt("Unescaped '{a}'.", line, + from + l, c); + } + if (b) { + switch (s.charAt(l)) { + case '?': + case '+': + case '*': + l += 1; + if (s.charAt(l) === '?') { + l += 1; + } + break; + case '{': + l += 1; + c = s.charAt(l); + if (c < '0' || c > '9') { + warningAt( +"Expected a number and instead saw '{a}'.", line, from + l, c); + } + l += 1; + low = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + low = +c + (low * 10); + } + high = low; + if (c === ',') { + l += 1; + high = Infinity; + c = s.charAt(l); + if (c >= '0' && c <= '9') { + l += 1; + high = +c; + for (;;) { + c = s.charAt(l); + if (c < '0' || c > '9') { + break; + } + l += 1; + high = +c + (high * 10); + } + } + } + if (s.charAt(l) !== '}') { + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); + } else { + l += 1; + } + if (s.charAt(l) === '?') { + l += 1; + } + if (low > high) { + warningAt( +"'{a}' should not be greater than '{b}'.", line, from + l, low, high); + } + } + } + } + c = s.substr(0, l - 1); + character += l; + s = s.substr(l); + return it('(regexp)', c); + } + return it('(punctuator)', t); + + // punctuator + + case '#': + return it('(punctuator)', t); + default: + return it('(punctuator)', t); + } + } + } + } + }; + }()); + + + function addlabel(t, type) { + + if (t === 'hasOwnProperty') { + warning("'hasOwnProperty' is a really bad name."); + } + +// Define t in the current function in the current scope. + + if (is_own(funct, t) && !funct['(global)']) { + if (funct[t] === true) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + } else { + if (!option.shadow) + warning("'{a}' is already defined.", nexttoken, t); + } + } + + funct[t] = type; + if (funct['(global)']) { + global[t] = funct; + if (is_own(implied, t)) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + + + function doOption() { + var b, obj, filter, o = nexttoken.value, t, v; + switch (o) { + case '*/': + error("Unbegun comment."); + break; + case '/*members': + case '/*member': + o = '/*members'; + if (!membersOnly) { + membersOnly = {}; + } + obj = membersOnly; + break; + case '/*jshint': + case '/*jslint': + obj = option; + filter = boolOptions; + break; + case '/*global': + obj = predefined; + break; + default: + error("What?"); + } + t = lex.token(); +loop: for (;;) { + for (;;) { + if (t.type === 'special' && t.value === '*/') { + break loop; + } + if (t.id !== '(endline)' && t.id !== ',') { + break; + } + t = lex.token(); + } + if (t.type !== '(string)' && t.type !== '(identifier)' && + o !== '/*members') { + error("Bad option.", t); + } + v = lex.token(); + if (v.id === ':') { + v = lex.token(); + if (obj === membersOnly) { + error("Expected '{a}' and instead saw '{b}'.", + t, '*/', ':'); + } + if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.white = true; + obj.indent = b; + } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxerr = b; + } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { + b = +v.value; + if (typeof b !== 'number' || !isFinite(b) || b <= 0 || + Math.floor(b) !== b) { + error("Expected a small integer and instead saw '{a}'.", + v, v.value); + } + obj.maxlen = b; + } else if (v.value === 'true') { + obj[t.value] = true; + } else if (v.value === 'false') { + obj[t.value] = false; + } else { + error("Bad option value.", v); + } + t = lex.token(); + } else { + if (o === '/*jshint' || o === '/*jslint') { + error("Missing option value.", t); + } + obj[t.value] = false; + t = v; + } + } + if (filter) { + assume(); + } + } + + +// We need a peek function. If it has an argument, it peeks that much farther +// ahead. It is used to distinguish +// for ( var i in ... +// from +// for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + + +// Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (token.id) { + case '(number)': + if (nexttoken.id === '.') { + warning("A dot following a number can be confused with a decimal point.", token); + } + break; + case '-': + if (nexttoken.id === '-' || nexttoken.id === '--') { + warning("Confusing minusses."); + } + break; + case '+': + if (nexttoken.id === '+' || nexttoken.id === '++') { + warning("Confusing plusses."); + } + break; + } + if (token.type === '(string)' || token.identifier) { + anonname = token.value; + } + + if (id && nexttoken.id !== id) { + if (t) { + if (nexttoken.id === '(end)') { + warning("Unmatched '{a}'.", t, t.id); + } else { + warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + nexttoken, id, t.id, t.line, nexttoken.value); + } + } else if (nexttoken.type !== '(identifier)' || + nexttoken.value !== id) { + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, id, nexttoken.value); + } + } + prevtoken = token; + token = nexttoken; + for (;;) { + nexttoken = lookahead.shift() || lex.token(); + if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { + return; + } + if (nexttoken.type === 'special') { + doOption(); + } else { + if (nexttoken.id !== '(endline)') { + break; + } + } + } + } + + +// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false; + + if (nexttoken.id === '(end)') + error("Unexpected early end of program.", token); + + advance(); + if (initial) { + anonname = 'anonymous'; + funct['(verb)'] = token.value; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (nexttoken.type === '(number)' && token.id === '.') { + warning("A leading decimal point can be confused with a dot: '.{a}'.", + token, nexttoken.value); + advance(); + return token; + } else { + error("Expected an identifier and instead saw '{a}'.", + token, token.id); + } + } + while (rbp < nexttoken.lbp) { + isArray = token.value == 'Array'; + advance(); + if (isArray && token.id == '(' && nexttoken.id == ')') + warning("Use the array literal notation [].", token); + if (token.led) { + left = token.led(left); + } else { + error("Expected an operator and instead saw '{a}'.", + token, token.id); + } + } + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white) { + if (left.character !== right.from && left.line === right.line) { + warning("Unexpected space after '{a}'.", right, left.value); + } + } + } + + function nobreak(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && (left.character !== right.from || left.line !== right.line)) { + warning("Unexpected space before '{a}'.", right, right.value); + } + } + + function nospace(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.line === right.line && left.character === right.from) { + warning("Missing space after '{a}'.", + nexttoken, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (!option.laxbreak && left.line !== right.line) { + warning("Bad line breaking before '{a}'.", right, right.id); + } else if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.character === right.from) { + warning("Missing space after '{a}'.", + nexttoken, left.value); + } + } + } + + function indentation(bias) { + var i; + if (option.white && nexttoken.id !== '(end)') { + i = indent + (bias || 0); + if (nexttoken.from !== i) { + warning( +"Expected '{a}' to have an indentation at {b} instead at {c}.", + nexttoken, nexttoken.value, i, nexttoken.from); + } + } + } + + function nolinebreak(t) { + t = t || token; + if (t.line !== nexttoken.line) { + warning("Line breaking error '{a}'.", t, t.value); + } + } + + + function comma() { + if (token.line !== nexttoken.line) { + if (!option.laxbreak) { + warning("Bad line breaking before '{a}'.", token, nexttoken.id); + } + } else if (token.character !== nexttoken.from && option.white) { + warning("Unexpected space after '{a}'.", nexttoken, token.value); + } + advance(','); + nonadjacent(token, nexttoken); + } + + +// Functional constructors for making the symbols that will be inherited by +// tokens. + + function symbol(s, p) { + var x = syntax[s]; + if (!x || typeof x !== 'object') { + syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + + function delim(s) { + return symbol(s, 0); + } + + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === 'function') ? f : function () { + this.right = expression(150); + this.arity = 'unary'; + if (this.id === '++' || this.id === '--') { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!this.right.identifier || this.right.reserved) && + this.right.id !== '.' && this.right.id !== '[') { + warning("Bad operand.", this); + } + } + return this; + }; + return x; + } + + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + + function reserve(s, f) { + var x = type(s, f); + x.identifier = x.reserved = true; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === 'function') { + v(this); + } + return this; + }); + } + + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.led = function (left) { + if (!w) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + } + if (typeof f === 'function') { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function relation(s, f) { + var x = symbol(s, 100); + x.led = function (left) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + var right = expression(100); + if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { + warning("Use the isNaN function to compare with NaN.", this); + } else if (f) { + f.apply(this, [left, right]); + } + if (left.id === '!') { + warning("Confusing use of '{a}'.", left, '!'); + } + if (right.id === '!') { + warning("Confusing use of '{a}'.", left, '!'); + } + this.left = left; + this.right = right; + return this; + }; + return x; + } + + + function isPoorRelation(node) { + return node && + ((node.type === '(number)' && +node.value === 0) || + (node.type === '(string)' && node.value === '') || + (node.type === 'null' && !option.eqnull) || + node.type === 'true' || + node.type === 'false' || + node.type === 'undefined'); + } + + + function assignop(s, f) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + var l; + that.left = left; + if (predefined[left.value] === false && + scope[left.value]['(global)'] === true) { + warning("Read only.", left); + } else if (left['function']) { + warning("'{a}' is a function.", left, left.value); + } + if (left) { + if (left.id === '.' || left.id === '[') { + if (!left.left || left.left.value === 'arguments') { + warning('Bad assignment.', that); + } + that.right = expression(19); + return that; + } else if (left.identifier && !left.reserved) { + if (funct[left.value] === 'exception') { + warning("Do not assign to the exception parameter.", left); + } + that.right = expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment and instead saw a function invocation.", + token); + } + } + error("Bad assignment.", that); + }, 20); + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === 'function') ? f : function (left) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", that, that.id); + } + nonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + if (left) { + if (left.id === '.' || left.id === '[' || + (left.identifier && !left.reserved)) { + expression(19); + return that; + } + if (left === syntax['function']) { + warning( +"Expected an identifier in an assignment, and instead saw a function invocation.", + token); + } + return that; + } + error("Bad assignment.", that); + }, 20); + } + + + function suffix(s, f) { + var x = symbol(s, 150); + x.led = function (left) { + if (option.plusplus) { + warning("Unexpected use of '{a}'.", this, this.id); + } else if ((!left.identifier || left.reserved) && + left.id !== '.' && left.id !== '[') { + warning("Bad operand.", this); + } + this.left = left; + return this; + }; + return x; + } + + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + function optionalidentifier(fnparam) { + if (nexttoken.identifier) { + advance(); + if (token.reserved && !option.es5) { + // `undefined` as a function param is a common pattern to protect + // against the case when somebody does `undefined = true` and + // help with minification. More info: https://gist.github.com/315916 + if (!fnparam || token.value != 'undefined') { + warning("Expected an identifier and instead saw '{a}' (a reserved word).", + token, token.id); + } + } + return token.value; + } + } + + // fnparam means that this identifier is being defined as a function + // argument + function identifier(fnparam) { + var i = optionalidentifier(fnparam); + if (i) { + return i; + } + if (token.id === 'function' && nexttoken.id === '(') { + warning("Missing name in function declaration."); + } else { + error("Expected an identifier and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (nexttoken.id !== ';' || noreach) { + return; + } + for (;;) { + t = peek(i); + if (t.reach) { + return; + } + if (t.id !== '(endline)') { + if (t.id === 'function') { + warning( +"Inner functions should be listed at the top of the outer function.", t); + break; + } + warning("Unreachable '{a}' after '{b}'.", t, t.value, s); + break; + } + i += 1; + } + } + + + function statement(noindent) { + var i = indent, r, s = scope, t = nexttoken; + +// We don't like the empty statement. + + if (t.id === ';') { + warning("Unnecessary semicolon.", t); + advance(';'); + return; + } + +// Is this a labelled statement? + + if (t.identifier && !t.reserved && peek().id === ':') { + advance(); + advance(':'); + scope = Object.create(s); + addlabel(t.value, 'label'); + if (!nexttoken.labelled) { + warning("Label '{a}' on {b} statement.", + nexttoken, t.value, nexttoken.value); + } + if (jx.test(t.value + ':')) { + warning("Label '{a}' looks like a javascript url.", + t, t.value); + } + nexttoken.label = t.value; + t = nexttoken; + } + +// Parse the statement. + + if (!noindent) { + indentation(); + } + r = expression(0, true); + +// Look for the final semicolon. + + if (!t.block) { + if (!option.expr && (!r || !r.exps)) { + warning("Expected an assignment or function call and instead saw an expression.", token); + } else if (option.nonew && r.id === '(' && r.left.id === 'new') { + warning("Do not use 'new' for side effects."); + } + if (nexttoken.id !== ';') { + if (!option.asi && !(option.lastsemic && nexttoken.id == '}' && nexttoken.line == token.line)) { + warningAt("Missing semicolon.", token.line, token.from + token.value.length); + } + } else { + adjacent(token, nexttoken); + advance(';'); + nonadjacent(token, nexttoken); + } + } + +// Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function use_strict() { + if (nexttoken.value === 'use strict') { + if (strict_mode) { + warning("Unnecessary \"use strict\"."); + } + advance(); + advance(';'); + strict_mode = true; + option.newcap = true; + option.undef = true; + return true; + } else { + return false; + } + } + + + function statements(begin) { + var a = [], f, p; + + while (!nexttoken.reach && nexttoken.id !== '(end)') { + if (nexttoken.id === ';') { + warning("Unnecessary semicolon."); + advance(';'); + } else { + a.push(statement()); + } + } + return a; + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + */ + function block(ordinary, stmt) { + var a, + b = inblock, + old_indent = indent, + m = strict_mode, + s = scope, + t; + + inblock = ordinary; + scope = Object.create(scope); + nonadjacent(token, nexttoken); + t = nexttoken; + + if (nexttoken.id === '{') { + advance('{'); + if (nexttoken.id !== '}' || token.line !== nexttoken.line) { + indent += option.indent; + while (!ordinary && nexttoken.from > indent) { + indent += option.indent; + } + if (!ordinary && !use_strict() && !m && option.strict && + funct['(context)']['(global)']) { + warning("Missing \"use strict\" statement."); + } + a = statements(); + strict_mode = m; + indent -= option.indent; + indentation(); + } + advance('}', t); + indent = old_indent; + } else if (!ordinary) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + } else { + if (!stmt || option.curly) + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, '{', nexttoken.value); + + noreach = true; + a = [statement()]; + noreach = false; + } + funct['(verb)'] = null; + scope = s; + inblock = b; + if (ordinary && option.noempty && (!a || a.length === 0)) { + warning("Empty block."); + } + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== 'boolean') { + warning("Unexpected /*member '{a}'.", token, m); + } + if (typeof member[m] === 'number') { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(token) { + var name = token.value, line = token.line, a = implied[name]; + if (typeof a === 'function') { + a = false; + } + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + +// Build the syntax table by declaring the syntactic elements of the language. + + type('(number)', function () { + return this; + }); + type('(string)', function () { + return this; + }); + + syntax['(identifier)'] = { + type: '(identifier)', + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + if (typeof s === 'function') { + +// Protection against accidental inheritance. + + s = undefined; + } else if (typeof s === 'boolean') { + f = funct; + funct = functions[0]; + addlabel(v, 'var'); + s = funct; + funct = f; + } + +// The name is in scope and defined in the current function. + + if (funct === s) { + +// Change 'unused' to 'var', and reject labels. + + switch (funct[v]) { + case 'unused': + funct[v] = 'var'; + break; + case 'unction': + funct[v] = 'function'; + this['function'] = true; + break; + case 'function': + this['function'] = true; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + } + +// The name is not defined in the function. If we are in the global scope, +// then we have an undefined variable. +// +// Operators typeof and delete do not raise runtime errors even if the base +// object of a reference is null so no need to display warning if we're +// inside of typeof or delete. + + } else if (funct['(global)']) { + if (anonname != 'typeof' && anonname != 'delete' && + option.undef && typeof predefined[v] !== 'boolean') { + warning("'{a}' is not defined.", token, v); + } + note_implied(token); + +// If the name is already defined in the current +// function, but not as outer, then there is a scope error. + + } else { + switch (funct[v]) { + case 'closure': + case 'function': + case 'var': + case 'unused': + warning("'{a}' used out of scope.", token, v); + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + break; + case 'outer': + case 'global': + break; + default: + +// If the name is defined in an outer function, make an outer entry, and if +// it was unused, make it var. + + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("'{a}' is not allowed.", token, v); + note_implied(token); + } else if (typeof s !== 'object') { + +// Operators typeof and delete do not raise runtime errors even if the base object of +// a reference is null so no need to display warning if we're inside of typeof or delete. + + if (anonname != 'typeof' && anonname != 'delete' && option.undef) { + warning("'{a}' is not defined.", token, v); + } else { + funct[v] = true; + } + note_implied(token); + } else { + switch (s[v]) { + case 'function': + case 'unction': + this['function'] = true; + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'var': + case 'unused': + s[v] = 'closure'; + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'closure': + case 'parameter': + funct[v] = s['(global)'] ? 'global' : 'outer'; + break; + case 'label': + warning("'{a}' is a statement label.", token, v); + } + } + } + } + return this; + }, + led: function () { + error("Expected an operator and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + }; + + type('(regexp)', function () { + return this; + }); + + +// ECMAScript parser + + delim('(endline)'); + delim('(begin)'); + delim('(end)').reach = true; + delim(''); + delim('(error)').reach = true; + delim('}').reach = true; + delim(')'); + delim(']'); + delim('"').reach = true; + delim("'").reach = true; + delim(';'); + delim(':').reach = true; + delim(','); + delim('#'); + delim('@'); + reserve('else'); + reserve('case').reach = true; + reserve('catch'); + reserve('default').reach = true; + reserve('finally'); + reservevar('arguments', function (x) { + if (strict_mode && funct['(global)']) { + warning("Strict violation.", x); + } + }); + reservevar('eval'); + reservevar('false'); + reservevar('Infinity'); + reservevar('NaN'); + reservevar('null'); + reservevar('this', function (x) { + if (strict_mode && ((funct['(statement)'] && + funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { + warning("Strict violation.", x); + } + }); + reservevar('true'); + reservevar('undefined'); + assignop('=', 'assign', 20); + assignop('+=', 'assignadd', 20); + assignop('-=', 'assignsub', 20); + assignop('*=', 'assignmult', 20); + assignop('/=', 'assigndiv', 20).nud = function () { + error("A regular expression literal can be confused with '/='."); + }; + assignop('%=', 'assignmod', 20); + bitwiseassignop('&=', 'assignbitand', 20); + bitwiseassignop('|=', 'assignbitor', 20); + bitwiseassignop('^=', 'assignbitxor', 20); + bitwiseassignop('<<=', 'assignshiftleft', 20); + bitwiseassignop('>>=', 'assignshiftright', 20); + bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); + infix('?', function (left, that) { + that.left = left; + that.right = expression(10); + advance(':'); + that['else'] = expression(10); + return that; + }, 30); + + infix('||', 'or', 40); + infix('&&', 'and', 50); + bitwise('|', 'bitor', 70); + bitwise('^', 'bitxor', 80); + bitwise('&', 'bitand', 90); + relation('==', function (left, right) { + var eqnull = option.eqnull && + (left.value == 'null' || right.value == 'null'); + + if (!eqnull && option.eqeqeq) { + warning("Expected '{a}' and instead saw '{b}'.", + this, '===', '=='); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, '===', left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + this, '===', right.value); + } + return this; + }); + relation('==='); + relation('!=', function (left, right) { + if (option.eqeqeq) { + warning("Expected '{a}' and instead saw '{b}'.", + this, '!==', '!='); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + this, '!==', right.value); + } + return this; + }); + relation('!=='); + relation('<'); + relation('>'); + relation('<='); + relation('>='); + bitwise('<<', 'shiftleft', 120); + bitwise('>>', 'shiftright', 120); + bitwise('>>>', 'shiftrightunsigned', 120); + infix('in', 'in', 120); + infix('instanceof', 'instanceof', 120); + infix('+', function (left, that) { + var right = expression(130); + if (left && right && left.id === '(string)' && right.id === '(string)') { + left.value += right.value; + left.character = right.character; + if (!option.scripturl && jx.test(left.value)) { + warning("JavaScript URL.", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix('+', 'num'); + prefix('+++', function () { + warning("Confusing pluses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('+++', function (left) { + warning("Confusing pluses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('-', 'sub', 130); + prefix('-', 'neg'); + prefix('---', function () { + warning("Confusing minuses."); + this.right = expression(150); + this.arity = 'unary'; + return this; + }); + infix('---', function (left) { + warning("Confusing minuses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix('*', 'mult', 140); + infix('/', 'div', 140); + infix('%', 'mod', 140); + + suffix('++', 'postinc'); + prefix('++', 'preinc'); + syntax['++'].exps = true; + + suffix('--', 'postdec'); + prefix('--', 'predec'); + syntax['--'].exps = true; + prefix('delete', function () { + var p = expression(0); + if (!p || (p.id !== '.' && p.id !== '[')) { + warning("Variables should not be deleted."); + } + this.first = p; + return this; + }).exps = true; + + prefix('~', function () { + if (option.bitwise) { + warning("Unexpected '{a}'.", this, '~'); + } + expression(150); + return this; + }); + + prefix('!', function () { + this.right = expression(150); + this.arity = 'unary'; + if (bang[this.right.id] === true) { + warning("Confusing use of '{a}'.", this, '!'); + } + return this; + }); + prefix('typeof', 'typeof'); + prefix('new', function () { + var c = expression(155), i; + if (c && c.id !== 'function') { + if (c.identifier) { + c['new'] = true; + switch (c.value) { + case 'Object': + warning("Use the object literal notation {}.", token); + break; + case 'Number': + case 'String': + case 'Boolean': + case 'Math': + case 'JSON': + warning("Do not use {a} as a constructor.", token, c.value); + break; + case 'Function': + if (!option.evil) { + warning("The Function constructor is eval."); + } + break; + case 'Date': + case 'RegExp': + break; + default: + if (c.id !== 'function') { + i = c.value.substr(0, 1); + if (option.newcap && (i < 'A' || i > 'Z')) { + warning("A constructor name should start with an uppercase letter.", token); + } + } + } + } else { + if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + warning("Bad constructor.", token); + } + } + } else { + if (!option.supernew) + warning("Weird construction. Delete 'new'.", this); + } + adjacent(token, nexttoken); + if (nexttoken.id !== '(' && !option.supernew) { + warning("Missing '()' invoking a constructor."); + } + this.first = c; + return this; + }); + syntax['new'].exps = true; + + prefix('void').exps = true; + + infix('.', function (left, that) { + adjacent(prevtoken, token); + nobreak(); + var m = identifier(); + if (typeof m === 'string') { + countMember(m); + } + that.left = left; + that.right = m; + if (option.noarg && left && left.value === 'arguments' && + (m === 'callee' || m === 'caller')) { + warning("Avoid arguments.{a}.", left, m); + } else if (!option.evil && left && left.value === 'document' && + (m === 'write' || m === 'writeln')) { + warning("document.write can be a form of eval.", left); + } + if (!option.evil && (m === 'eval' || m === 'execScript')) { + warning('eval is evil.'); + } + return that; + }, 160, true); + + infix('(', function (left, that) { + if (prevtoken.id !== '}' && prevtoken.id !== ')') { + nobreak(prevtoken, token); + } + nospace(); + if (option.immed && !left.immed && left.id === 'function') { + warning("Wrap an immediate function invocation in parentheses " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself."); + } + var n = 0, + p = []; + if (left) { + if (left.type === '(identifier)') { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if (left.value !== 'Number' && left.value !== 'String' && + left.value !== 'Boolean' && + left.value !== 'Date') { + if (left.value === 'Math') { + warning("Math is not a function.", left); + } else if (option.newcap) { + warning( +"Missing 'new' prefix when invoking a constructor.", left); + } + } + } + } + } + if (nexttoken.id !== ')') { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')'); + nospace(prevtoken, token); + if (typeof left === 'object') { + if (left.value === 'parseInt' && n === 1) { + warning("Missing radix parameter.", left); + } + if (!option.evil) { + if (left.value === 'eval' || left.value === 'Function' || + left.value === 'execScript') { + warning("eval is evil.", left); + } else if (p[0] && p[0].id === '(string)' && + (left.value === 'setTimeout' || + left.value === 'setInterval')) { + warning( + "Implied eval is evil. Pass a function instead of a string.", left); + } + } + if (!left.identifier && left.id !== '.' && left.id !== '[' && + left.id !== '(' && left.id !== '&&' && left.id !== '||' && + left.id !== '?') { + warning("Bad invocation.", left); + } + } + that.left = left; + return that; + }, 155, true).exps = true; + + prefix('(', function () { + nospace(); + if (nexttoken.id === 'function') { + nexttoken.immed = true; + } + var v = expression(0); + advance(')', this); + nospace(prevtoken, token); + if (option.immed && v.id === 'function') { + if (nexttoken.id === '(') { + warning( +"Move the invocation into the parens that contain the function.", nexttoken); + } else { + warning( +"Do not wrap function literals in parens unless they are to be immediately invoked.", + this); + } + } + return v; + }); + + infix('[', function (left, that) { + nobreak(prevtoken, token); + nospace(); + var e = expression(0), s; + if (e && e.type === '(string)') { + if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { + warning("eval is evil.", that); + } + countMember(e.value); + if (!option.sub && ix.test(e.value)) { + s = syntax[e.value]; + if (!s || !s.reserved) { + warning("['{a}'] is better written in dot notation.", + e, e.value); + } + } + } + advance(']', that); + nospace(prevtoken, token); + that.left = left; + that.right = e; + return that; + }, 160, true); + + prefix('[', function () { + var b = token.line !== nexttoken.line; + this.first = []; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + while (nexttoken.id !== '(end)') { + while (nexttoken.id === ',') { + warning("Extra comma."); + advance(','); + } + if (nexttoken.id === ']') { + break; + } + if (b && token.line !== nexttoken.line) { + indentation(); + } + this.first.push(expression(10)); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ']' && !option.es5) { + warning("Extra comma.", token); + break; + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance(']', this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(true); + if (!id) { + if (nexttoken.id === '(string)') { + id = nexttoken.value; + advance(); + } else if (nexttoken.id === '(number)') { + id = nexttoken.value.toString(); + advance(); + } + } + return id; + } + + + function functionparams() { + var i, t = nexttoken, p = []; + advance('('); + nospace(); + if (nexttoken.id === ')') { + advance(')'); + nospace(prevtoken, token); + return; + } + for (;;) { + i = identifier(true); + p.push(i); + addlabel(i, 'parameter'); + if (nexttoken.id === ',') { + comma(); + } else { + advance(')', t); + nospace(prevtoken, token); + return p; + } + } + } + + + function doFunction(i, statement) { + var f, + oldOption = option, + oldScope = scope; + + option = Object.create(option); + scope = Object.create(scope); + + funct = { + '(name)' : i || '"' + anonname + '"', + '(line)' : nexttoken.line, + '(context)' : funct, + '(breakage)' : 0, + '(loopage)' : 0, + '(scope)' : scope, + '(statement)': statement + }; + f = funct; + token.funct = funct; + functions.push(funct); + if (i) { + addlabel(i, 'function'); + } + funct['(params)'] = functionparams(); + + block(false); + scope = oldScope; + option = oldOption; + funct['(last)'] = token.line; + funct = funct['(context)']; + return f; + } + + + (function (x) { + x.nud = function () { + var b, f, i, j, p, seen = {}, t; + + b = token.line !== nexttoken.line; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + for (;;) { + if (nexttoken.id === '}') { + break; + } + if (b) { + indentation(); + } + if (nexttoken.value === 'get' && peek().id !== ':') { + advance('get'); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + if (!option.loopfunc && funct['(loopage)']) { + warning("Don't make functions within a loop.", t); + } + p = f['(params)']; + if (p) { + warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); + } + adjacent(token, nexttoken); + advance(','); + indentation(); + advance('set'); + j = property_name(); + if (i !== j) { + error("Expected {a} and instead saw {b}.", token, i, j); + } + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + p = f['(params)']; + if (!p || p.length !== 1 || p[0] !== 'value') { + warning("Expected (value) in set {a} function.", t, i); + } + } else { + i = property_name(); + if (typeof i !== 'string') { + break; + } + advance(':'); + nonadjacent(token, nexttoken); + expression(10); + } + if (seen[i] === true) { + warning("Duplicate member '{a}'.", nexttoken, i); + } + seen[i] = true; + countMember(i); + if (nexttoken.id === ',') { + comma(); + if (nexttoken.id === ',') { + warning("Extra comma.", token); + } else if (nexttoken.id === '}' && !option.es5) { + warning("Extra comma.", token); + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance('}', this); + return this; + }; + x.fud = function () { + error("Expected to see a statement and instead saw a block.", token); + }; + }(delim('{'))); + + var varstatement = stmt('var', function (prefix) { + // JavaScript does not have block scope. It only has function scope. So, + // declaring a variable in a block can have unexpected consequences. + var id, name, value; + + if (funct['(onevar)'] && option.onevar) { + warning("Too many var statements."); + } else if (!funct['(global)']) { + funct['(onevar)'] = true; + } + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (funct['(global)'] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, 'unused'); + if (prefix) { + break; + } + name = token; + this.first.push(token); + if (nexttoken.id === '=') { + nonadjacent(token, nexttoken); + advance('='); + nonadjacent(token, nexttoken); + if (nexttoken.id === 'undefined') { + warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); + } + if (peek(0).id === '=' && nexttoken.identifier) { + error("Variable {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + if (nexttoken.id !== ',') { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + blockstmt('function', function () { + if (inblock) { + warning( +"Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token); + + } + var i = identifier(); + adjacent(token, nexttoken); + addlabel(i, 'unction'); + doFunction(i, true); + if (nexttoken.id === '(' && nexttoken.line === token.line) { + error( +"Function declarations are not invocable. Wrap the whole function invocation in parens."); + } + return this; + }); + + prefix('function', function () { + var i = optionalidentifier(); + if (i) { + adjacent(token, nexttoken); + } else { + nonadjacent(token, nexttoken); + } + doFunction(i); + if (!option.loopfunc && funct['(loopage)']) { + warning("Don't make functions within a loop."); + } + return this; + }); + + blockstmt('if', function () { + var t = nexttoken; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + if (nexttoken.id === 'else') { + nonadjacent(token, nexttoken); + advance('else'); + if (nexttoken.id === 'if' || nexttoken.id === 'switch') { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt('try', function () { + var b, e, s; + + block(false); + if (nexttoken.id === 'catch') { + advance('catch'); + nonadjacent(token, nexttoken); + advance('('); + s = scope; + scope = Object.create(s); + e = nexttoken.value; + if (nexttoken.type !== '(identifier)') { + warning("Expected an identifier and instead saw '{a}'.", + nexttoken, e); + } else { + addlabel(e, 'exception'); + } + advance(); + advance(')'); + block(false); + b = true; + scope = s; + } + if (nexttoken.id === 'finally') { + advance('finally'); + block(false); + return; + } else if (!b) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'catch', nexttoken.value); + } + return this; + }); + + blockstmt('while', function () { + var t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }).labelled = true; + + reserve('with'); + + blockstmt('switch', function () { + var t = nexttoken, + g = false; + funct['(breakage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + this.condition = expression(20); + advance(')', t); + nospace(prevtoken, token); + nonadjacent(token, nexttoken); + t = nexttoken; + advance('{'); + nonadjacent(token, nexttoken); + indent += option.indent; + this.cases = []; + for (;;) { + switch (nexttoken.id) { + case 'case': + switch (funct['(verb)']) { + case 'break': + case 'case': + case 'continue': + case 'return': + case 'switch': + case 'throw': + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'case'.", + token); + } + } + indentation(-option.indent); + advance('case'); + this.cases.push(expression(20)); + g = true; + advance(':'); + funct['(verb)'] = 'case'; + break; + case 'default': + switch (funct['(verb)']) { + case 'break': + case 'continue': + case 'return': + case 'throw': + break; + default: + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'default'.", + token); + } + } + indentation(-option.indent); + advance('default'); + g = true; + advance(':'); + break; + case '}': + indent -= option.indent; + indentation(); + advance('}', t); + if (this.cases.length === 1 || this.condition.id === 'true' || + this.condition.id === 'false') { + warning("This 'switch' should be an 'if'.", this); + } + funct['(breakage)'] -= 1; + funct['(verb)'] = undefined; + return; + case '(end)': + error("Missing '{a}'.", nexttoken, '}'); + return; + default: + if (g) { + switch (token.id) { + case ',': + error("Each value should have its own case label."); + return; + case ':': + statements(); + break; + default: + error("Missing ':' on a case clause.", token); + } + } else { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, 'case', nexttoken.value); + } + } + } + }).labelled = true; + + stmt('debugger', function () { + if (!option.debug) { + warning("All 'debugger' statements should be removed."); + } + return this; + }).exps = true; + + (function () { + var x = stmt('do', function () { + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + this.first = block(true); + advance('while'); + var t = nexttoken; + nonadjacent(token, t); + advance('('); + nospace(); + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + advance(')', t); + nospace(prevtoken, token); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt('for', function () { + var s, t = nexttoken; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + nonadjacent(this, t); + nospace(); + if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement, true); + } else { + switch (funct[nexttoken.value]) { + case 'unused': + funct[nexttoken.value] = 'var'; + break; + case 'var': + break; + default: + warning("Bad for in variable '{a}'.", + nexttoken, nexttoken.value); + } + advance(); + } + advance('in'); + expression(20); + advance(')', t); + s = block(true, true); + if (option.forin && (s.length > 1 || typeof s[0] !== 'object' || + s[0].value !== 'if')) { + warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this); + } + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } else { + if (nexttoken.id !== ';') { + if (nexttoken.id === 'var') { + advance('var'); + varstatement.fud.call(varstatement); + } else { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id !== ';') { + expression(20); + if (nexttoken.id === '=') { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance('='); + expression(20); + } + } + nolinebreak(token); + advance(';'); + if (nexttoken.id === ';') { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, ')', ';'); + } + if (nexttoken.id !== ')') { + for (;;) { + expression(0, 'for'); + if (nexttoken.id !== ',') { + break; + } + comma(); + } + } + advance(')', t); + nospace(prevtoken, token); + block(true, true); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + } + }).labelled = true; + + + stmt('break', function () { + var v = nexttoken.value; + if (funct['(breakage)'] === 0) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + nolinebreak(this); + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } + reachable('break'); + return this; + }).exps = true; + + + stmt('continue', function () { + var v = nexttoken.value; + if (funct['(breakage)'] === 0) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + nolinebreak(this); + if (nexttoken.id !== ';') { + if (token.line === nexttoken.line) { + if (funct[v] !== 'label') { + warning("'{a}' is not a statement label.", nexttoken, v); + } else if (scope[v] !== funct) { + warning("'{a}' is out of scope.", nexttoken, v); + } + this.first = nexttoken; + advance(); + } + } else if (!funct['(loopage)']) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + reachable('continue'); + return this; + }).exps = true; + + + stmt('return', function () { + nolinebreak(this); + if (nexttoken.id === '(regexp)') { + warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); + } + if (nexttoken.id !== ';' && !nexttoken.reach) { + nonadjacent(token, nexttoken); + this.first = expression(20); + } + reachable('return'); + return this; + }).exps = true; + + + stmt('throw', function () { + nolinebreak(this); + nonadjacent(token, nexttoken); + this.first = expression(20); + reachable('throw'); + return this; + }).exps = true; + +// Superfluous reserved words + + reserve('class'); + reserve('const'); + reserve('enum'); + reserve('export'); + reserve('extends'); + reserve('import'); + reserve('super'); + + reserve('let'); + reserve('yield'); + reserve('implements'); + reserve('interface'); + reserve('package'); + reserve('private'); + reserve('protected'); + reserve('public'); + reserve('static'); + + +// Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = nexttoken; + advance('{'); + if (nexttoken.id !== '}') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing '}' to match '{' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === '}') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } else if (nexttoken.id !== '(string)') { + warning("Expected a string and instead saw {a}.", + nexttoken, nexttoken.value); + } + if (o[nexttoken.value] === true) { + warning("Duplicate key '{a}'.", + nexttoken, nexttoken.value); + } else if (nexttoken.value === '__proto__') { + warning("Stupid key '{a}'.", + nexttoken, nexttoken.value); + } else { + o[nexttoken.value] = true; + } + advance(); + advance(':'); + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance('}'); + } + + function jsonArray() { + var t = nexttoken; + advance('['); + if (nexttoken.id !== ']') { + for (;;) { + if (nexttoken.id === '(end)') { + error("Missing ']' to match '[' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === ']') { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ',') { + error("Unexpected comma.", nexttoken); + } + jsonValue(); + if (nexttoken.id !== ',') { + break; + } + advance(','); + } + } + advance(']'); + } + + switch (nexttoken.id) { + case '{': + jsonObject(); + break; + case '[': + jsonArray(); + break; + case 'true': + case 'false': + case 'null': + case '(number)': + case '(string)': + advance(); + break; + case '-': + advance('-'); + if (token.character !== nexttoken.from) { + warning("Unexpected space after '-'.", token); + } + adjacent(token, nexttoken); + advance('(number)'); + break; + default: + error("Expected a JSON value.", nexttoken); + } + } + + +// The actual JSHINT function itself. + + var itself = function (s, o, g) { + var a, i, k; + JSHINT.errors = []; + predefined = Object.create(standard); + combine(predefined, g || {}); + if (o) { + a = o.predef; + if (a) { + if (Array.isArray(a)) { + for (i = 0; i < a.length; i += 1) { + predefined[a[i]] = true; + } + } else if (typeof a === 'object') { + k = Object.keys(a); + for (i = 0; i < k.length; i += 1) { + predefined[k[i]] = !!a[k[i]]; + } + } + } + option = o; + } else { + option = {}; + } + option.indent = option.indent || 4; + option.maxerr = option.maxerr || 50; + + tab = ''; + for (i = 0; i < option.indent; i += 1) { + tab += ' '; + } + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + '(global)': true, + '(name)': '(global)', + '(scope)': scope, + '(breakage)': 0, + '(loopage)': 0 + }; + functions = [funct]; + urls = []; + src = false; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + jsonmode = false; + warnings = 0; + lex.init(s); + prereg = true; + strict_mode = false; + + prevtoken = token = nexttoken = syntax['(begin)']; + assume(); + + try { + advance(); + switch (nexttoken.id) { + case '{': + case '[': + option.laxbreak = true; + jsonmode = true; + jsonValue(); + break; + default: + if (nexttoken.value === 'use strict') { + if (!option.globalstrict) + warning("Use the function form of \"use strict\"."); + use_strict(); + } + statements('lib'); + } + advance('(end)'); + } catch (e) { + if (e) { + JSHINT.errors.push({ + reason : e.message, + line : e.line || nexttoken.line, + character : e.character || nexttoken.from + }, null); + } + } + return JSHINT.errors.length === 0; + }; + + +// Data summary. + + itself.data = function () { + + var data = {functions: []}, fu, globals, implieds = [], f, i, j, + members = [], n, unused = [], v; + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (jsonmode) { + data.json = true; + } + + for (n in implied) { + if (is_own(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + for (n in f) { + if (is_own(f, n) && n.charAt(0) !== '(') { + v = f[n]; + if (v === 'unction') { + v = 'unused'; + } + if (Array.isArray(fu[v])) { + fu[v].push(n); + if (v === 'unused') { + unused.push({ + name: n, + line: f['(line)'], + 'function': f['(name)'] + }); + } + } + } + } + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + fu.name = f['(name)']; + fu.param = f['(params)']; + fu.line = f['(line)']; + fu.last = f['(last)']; + data.functions.push(fu); + } + + if (unused.length > 0) { + data.unused = unused; + } + + members = []; + for (n in member) { + if (typeof member[n] === 'number') { + data.member = member; + break; + } + } + + return data; + }; + + itself.report = function (option) { + var data = itself.data(); + + var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; + + function detail(h, array) { + var b, i, singularity; + if (array) { + o.push('
' + h + ' '); + array = array.sort(); + for (i = 0; i < array.length; i += 1) { + if (array[i] !== singularity) { + singularity = array[i]; + o.push((b ? ', ' : '') + singularity); + b = true; + } + } + o.push('
'); + } + } + + + if (data.errors || data.implieds || data.unused) { + err = true; + o.push('
Error:'); + if (data.errors) { + for (i = 0; i < data.errors.length; i += 1) { + c = data.errors[i]; + if (c) { + e = c.evidence || ''; + o.push('

Problem' + (isFinite(c.line) ? ' at line ' + + c.line + ' character ' + c.character : '') + + ': ' + c.reason.entityify() + + '

' + + (e && (e.length > 80 ? e.slice(0, 77) + '...' : + e).entityify()) + '

'); + } + } + } + + if (data.implieds) { + s = []; + for (i = 0; i < data.implieds.length; i += 1) { + s[i] = '' + data.implieds[i].name + ' ' + + data.implieds[i].line + ''; + } + o.push('

Implied global: ' + s.join(', ') + '

'); + } + + if (data.unused) { + s = []; + for (i = 0; i < data.unused.length; i += 1) { + s[i] = '' + data.unused[i].name + ' ' + + data.unused[i].line + ' ' + + data.unused[i]['function'] + ''; + } + o.push('

Unused variable: ' + s.join(', ') + '

'); + } + if (data.json) { + o.push('

JSON: bad.

'); + } + o.push('
'); + } + + if (!option) { + + o.push('
'); + + if (data.urls) { + detail("URLs
", data.urls, '
'); + } + + if (data.json && !err) { + o.push('

JSON: good.

'); + } else if (data.globals) { + o.push('
Global ' + + data.globals.sort().join(', ') + '
'); + } else { + o.push('
No new global variables introduced.
'); + } + + for (i = 0; i < data.functions.length; i += 1) { + f = data.functions[i]; + + o.push('
' + f.line + '-' + + f.last + ' ' + (f.name || '') + '(' + + (f.param ? f.param.join(', ') : '') + ')
'); + detail('Unused', f.unused); + detail('Closure', f.closure); + detail('Variable', f['var']); + detail('Exception', f.exception); + detail('Outer', f.outer); + detail('Global', f.global); + detail('Label', f.label); + } + + if (data.member) { + a = Object.keys(data.member); + if (a.length) { + a = a.sort(); + m = '
/*members ';
+                    l = 10;
+                    for (i = 0; i < a.length; i += 1) {
+                        k = a[i];
+                        n = k.name();
+                        if (l + n.length > 72) {
+                            o.push(m + '
'); + m = ' '; + l = 1; + } + l += n.length + 2; + if (data.member[k] === 1) { + n = '' + n + ''; + } + if (i < a.length - 1) { + n += ', '; + } + m += n; + } + o.push(m + '
*/
'); + } + o.push('
'); + } + } + return o.join(''); + }; + itself.jshint = itself; + + itself.edition = '2011-04-16'; + + return itself; + +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports == 'object' && exports) + exports.JSHINT = JSHINT; + + + +(function (args) { + var filenames = [], + optstr, // arg1=val1,arg2=val2,... + predef, // global1=override,global2,global3,... + opts = { rhino: true }, + retval = 0; + + args.forEach(function(arg){ + if (arg.indexOf("=") > -1){ + //first time it's the options + if (!optstr){ + optstr = arg; + } else if (!predef) { + predef = arg; + } + } else { + filenames.push(arg); + } + }); + + if (filenames.length === 0) { + print('Usage: jshint.js file.js'); + quit(1); + } + + if (optstr) { + optstr.split(',').forEach(function (arg) { + var o = arg.split('='); + opts[o[0]] = (function (ov) { + switch (ov) { + case 'true': + return true; + case 'false': + return false; + default: + return ov; + } + })(o[1]); + }); + } + + if (predef) { + opts.predef = {}; + predef.split(',').forEach(function (arg) { + var global = arg.split('='); + opts.predef[global[0]] = (function (override) { + return (override === 'false') ? false : true; + })(global[1]); + }); + } + + filenames.forEach(function(name){ + + var input = readFile(name); + + if (!input) { + print('jshint: Couldn\'t open file ' + name); + quit(1); + } + + if (!JSHINT(input, opts)) { + for (var i = 0, err; err = JSHINT.errors[i]; i++) { + print(err.reason + ' (' + name + ':' + err.line + ':' + err.character + ')'); + print('> ' + (err.evidence || '').replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); + print(''); + } + retval = 1; + } + }); + + quit(retval); +}(arguments)); diff --git a/lib/yuitest-rhino-cli.js b/lib/yuitest-rhino-cli.js new file mode 100644 index 00000000..958286b4 --- /dev/null +++ b/lib/yuitest-rhino-cli.js @@ -0,0 +1,3955 @@ +/** + * YUI Test Framework + * @module yuitest + */ + +/** + * The root namespace for YUI Test. + * @class YUITest + * @static + */ + +var YUITest = { + version: "@VERSION@" +}; + + +/** + * Simple custom event implementation. + * @namespace YUITest + * @class EventTarget + * @constructor + */ +YUITest.EventTarget = function(){ + + /** + * Event handlers for the various events. + * @type Object + * @private + * @property _handlers + * @static + */ + this._handlers = {}; + +}; + +YUITest.EventTarget.prototype = { + + //restore prototype + constructor: YUITest.EventTarget, + + //------------------------------------------------------------------------- + // Event Handling + //------------------------------------------------------------------------- + + /** + * Adds a listener for a given event type. + * @param {String} type The type of event to add a listener for. + * @param {Function} listener The function to call when the event occurs. + * @return {void} + * @method attach + */ + attach: function(type, listener){ + if (typeof this._handlers[type] == "undefined"){ + this._handlers[type] = []; + } + + this._handlers[type].push(listener); + }, + + /** + * Adds a listener for a given event type. + * @param {String} type The type of event to add a listener for. + * @param {Function} listener The function to call when the event occurs. + * @return {void} + * @method subscribe + * @deprecated + */ + subscribe: function(type, listener){ + this.attach.apply(this, arguments); + }, + + /** + * Fires an event based on the passed-in object. + * @param {Object|String} event An object with at least a 'type' attribute + * or a string indicating the event name. + * @return {void} + * @method fire + */ + fire: function(event){ + if (typeof event == "string"){ + event = { type: event }; + } + if (!event.target){ + event.target = this; + } + + if (!event.type){ + throw new Error("Event object missing 'type' property."); + } + + if (this._handlers[event.type] instanceof Array){ + var handlers = this._handlers[event.type]; + for (var i=0, len=handlers.length; i < len; i++){ + handlers[i].call(this, event); + } + } + }, + + /** + * Removes a listener for a given event type. + * @param {String} type The type of event to remove a listener from. + * @param {Function} listener The function to remove from the event. + * @return {void} + * @method detach + */ + detach: function(type, listener){ + if (this._handlers[type] instanceof Array){ + var handlers = this._handlers[type]; + for (var i=0, len=handlers.length; i < len; i++){ + if (handlers[i] === listener){ + handlers.splice(i, 1); + break; + } + } + } + }, + + /** + * Removes a listener for a given event type. + * @param {String} type The type of event to remove a listener from. + * @param {Function} listener The function to remove from the event. + * @return {void} + * @method unsubscribe + * @deprecated + */ + unsubscribe: function(type, listener){ + this.detach.apply(this, arguments); + } + +}; + + +/** + * Object containing helper methods. + * @namespace YUITest + * @class Util + * @static + */ +YUITest.Util = { + + /** + * Mixes the own properties from the supplier onto the + * receiver. + * @param {Object} receiver The object to receive the properties. + * @param {Object} supplier The object to supply the properties. + * @return {Object} The receiver that was passed in. + * @method mix + * @static + */ + mix: function(receiver, supplier){ + + for (var prop in supplier){ + if (supplier.hasOwnProperty(prop)){ + receiver[prop] = supplier[prop]; + } + } + + return receiver; + }, + + /** + * Stub for JSON functionality. When the native JSON utility + * is available, it will be used. Otherwise, a stub object + * is created. Developers should override YUITest.Util.JSON + * when attempting to use it in environments where a native + * JSON utility is unavailable. + * @property JSON + * @type JSON + * @static + */ + JSON: typeof JSON != "undefined" ? JSON : { + stringify: function(){ + //TODO: Should include code to do this? + throw new Error("No JSON utility specified."); + } + } + +}; + + + +/** + * Object containing object helper methods. + * @namespace YUITest + * @class Object + * @static + */ +YUITest.Object = { + /** + * Property names that IE doesn't enumerate in for..in loops, even when they + * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to + * manually enumerate these properties. + * + * @property _forceEnum + * @type String[] + * @protected + * @static + */ + _forceEnum : [ + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toString', + 'toLocaleString', + 'valueOf' + ], + + /** + * `true` if this browser has the JScript enumeration bug that prevents + * enumeration of the properties named in the `_forceEnum` array, `false` + * otherwise. + * + * See: + * - + * - + * + * @property _hasEnumBug + * @type {Boolean} + * @protected + * @static + */ + _hasEnumBug : !{valueOf: 0}.propertyIsEnumerable('valueOf'), + + /** + * Determines whether or not the provided item is of type object + * or function. Note that arrays are also objects, so + * YUITest.Object.isObject([]) === true. + * @method isObject + * @static + * @param o The object to test. + * @param failfn {boolean} fail if the input is a function. + * @return {boolean} true if o is an object. + */ + _isObject : function(o, failfn) { + var t = typeof o; + return (o && (t === 'object' || (!failfn && (t === 'function' || typeof t === 'function')))) || false; + }, + + /** + * Returns an array containing the object's enumerable keys. Does not include + * prototype keys or non-enumerable keys. + * + * Note that keys are returned in enumeration order (that is, in the same order + * that they would be enumerated by a `for-in` loop), which may not be the same + * as the order in which they were defined. + * + * This method is an alias for the native ES5 `Object.keys()` method if + * available. + * + * @example + * + * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'}); + * // => ['a', 'b', 'c'] + * + * @method keys + * @param {Object} obj An object. + * @return {String[]} Array of keys. + * @static + */ + keys : Object.keys || function (obj) { + if (!YUITest.Object.isObject(obj)) { + throw new TypeError('Object.keys called on a non-object'); + } + + var keys = [], + i, key, len; + + for (key in obj) { + if (owns(obj, key)) { + keys.push(key); + } + } + + if (YUITest.Object._hasEnumBug) { + for (i = 0, len = YUITest.Object._forceEnum.length; i < len; ++i) { + key = YUITest.Object._forceEnum[i]; + + if (owns(obj, key)) { + keys.push(key); + } + } + } + + return keys; + } +}; + +/** + * Error is thrown whenever an assertion fails. It provides methods + * to more easily get at error information and also provides a base class + * from which more specific assertion errors can be derived. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @class AssertionError + * @constructor + */ +YUITest.AssertionError = function (message){ + + /** + * Error message. Must be duplicated to ensure browser receives it. + * @type String + * @property message + */ + this.message = message; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "Assert Error"; +}; + +YUITest.AssertionError.prototype = { + + //restore constructor + constructor: YUITest.AssertionError, + + /** + * Returns a fully formatted error for an assertion failure. This should + * be overridden by all subclasses to provide specific information. + * @method getMessage + * @return {String} A string describing the error. + */ + getMessage : function () { + return this.message; + }, + + /** + * Returns a string representation of the error. + * @method toString + * @return {String} A string representation of the error. + */ + toString : function () { + return this.name + ": " + this.getMessage(); + } + +}; + +/** + * ComparisonFailure is subclass of Error that is thrown whenever + * a comparison between two values fails. It provides mechanisms to retrieve + * both the expected and actual value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value that caused the assertion to fail. + * @namespace YUITest + * @extends AssertionError + * @class ComparisonFailure + * @constructor + */ +YUITest.ComparisonFailure = function (message, expected, actual){ + + //call superclass + YUITest.AssertionError.call(this, message); + + /** + * The expected value. + * @type Object + * @property expected + */ + this.expected = expected; + + /** + * The actual value. + * @type Object + * @property actual + */ + this.actual = actual; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ComparisonFailure"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ComparisonFailure.prototype = new YUITest.AssertionError; + +//restore constructor +YUITest.ComparisonFailure.prototype.constructor = YUITest.ComparisonFailure; + +/** + * Returns a fully formatted error for an assertion failure. This message + * provides information about the expected and actual values. + * @method getMessage + * @return {String} A string describing the error. + */ +YUITest.ComparisonFailure.prototype.getMessage = function(){ + return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" + + "\nActual: " + this.actual + " (" + (typeof this.actual) + ")"; +}; + +/** + * ShouldError is subclass of Error that is thrown whenever + * a test is expected to throw an error but doesn't. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @extends AssertionError + * @class ShouldError + * @constructor + */ +YUITest.ShouldError = function (message){ + + //call superclass + YUITest.AssertionError.call(this, message || "This test should have thrown an error but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ShouldError"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ShouldError.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.ShouldError.prototype.constructor = YUITest.ShouldError; + +/** + * ShouldFail is subclass of AssertionError that is thrown whenever + * a test was expected to fail but did not. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @extends YUITest.AssertionError + * @class ShouldFail + * @constructor + */ +YUITest.ShouldFail = function (message){ + + //call superclass + YUITest.AssertionError.call(this, message || "This test should fail but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ShouldFail"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ShouldFail.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.ShouldFail.prototype.constructor = YUITest.ShouldFail; + +/** + * UnexpectedError is subclass of AssertionError that is thrown whenever + * an error occurs within the course of a test and the test was not expected + * to throw an error. + * + * @param {Error} cause The unexpected error that caused this error to be + * thrown. + * @namespace YUITest + * @extends YUITest.AssertionError + * @class UnexpectedError + * @constructor + */ +YUITest.UnexpectedError = function (cause){ + + //call superclass + YUITest.AssertionError.call(this, "Unexpected error: " + cause.message); + + /** + * The unexpected error that occurred. + * @type Error + * @property cause + */ + this.cause = cause; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "UnexpectedError"; + + /** + * Stack information for the error (if provided). + * @type String + * @property stack + */ + this.stack = cause.stack; + +}; + +//inherit from YUITest.AssertionError +YUITest.UnexpectedError.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.UnexpectedError.prototype.constructor = YUITest.UnexpectedError; + +/** + * UnexpectedValue is subclass of Error that is thrown whenever + * a value was unexpected in its scope. This typically means that a test + * was performed to determine that a value was *not* equal to a certain + * value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} unexpected The unexpected value. + * @namespace YUITest + * @extends AssertionError + * @class UnexpectedValue + * @constructor + */ +YUITest.UnexpectedValue = function (message, unexpected){ + + //call superclass + YUITest.AssertionError.call(this, message); + + /** + * The unexpected value. + * @type Object + * @property unexpected + */ + this.unexpected = unexpected; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "UnexpectedValue"; + +}; + +//inherit from YUITest.AssertionError +YUITest.UnexpectedValue.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.UnexpectedValue.prototype.constructor = YUITest.UnexpectedValue; + +/** + * Returns a fully formatted error for an assertion failure. This message + * provides information about the expected and actual values. + * @method getMessage + * @return {String} A string describing the error. + */ +YUITest.UnexpectedValue.prototype.getMessage = function(){ + return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") "; +}; + + +/** + * Represents a stoppage in test execution to wait for an amount of time before + * continuing. + * @param {Function} segment A function to run when the wait is over. + * @param {int} delay The number of milliseconds to wait before running the code. + * @class Wait + * @namespace Test + * @constructor + * + */ +YUITest.Wait = function (segment, delay) { + + /** + * The segment of code to run when the wait is over. + * @type Function + * @property segment + */ + this.segment = (typeof segment == "function" ? segment : null); + + /** + * The delay before running the segment of code. + * @type int + * @property delay + */ + this.delay = (typeof delay == "number" ? delay : 0); +}; + + +/** + * The Assert object provides functions to test JavaScript values against + * known and expected results. Whenever a comparison (assertion) fails, + * an error is thrown. + * @namespace YUITest + * @class Assert + * @static + */ +YUITest.Assert = { + + /** + * The number of assertions performed. + * @property _asserts + * @type int + * @private + */ + _asserts: 0, + + //------------------------------------------------------------------------- + // Helper Methods + //------------------------------------------------------------------------- + + /** + * Formats a message so that it can contain the original assertion message + * in addition to the custom message. + * @param {String} customMessage The message passed in by the developer. + * @param {String} defaultMessage The message created by the error by default. + * @return {String} The final error message, containing either or both. + * @protected + * @static + * @method _formatMessage + */ + _formatMessage : function (customMessage, defaultMessage) { + if (typeof customMessage == "string" && customMessage.length > 0){ + return customMessage.replace("{message}", defaultMessage); + } else { + return defaultMessage; + } + }, + + /** + * Returns the number of assertions that have been performed. + * @method _getCount + * @protected + * @static + */ + _getCount: function(){ + return this._asserts; + }, + + /** + * Increments the number of assertions that have been performed. + * @method _increment + * @protected + * @static + */ + _increment: function(){ + this._asserts++; + }, + + /** + * Resets the number of assertions that have been performed to 0. + * @method _reset + * @protected + * @static + */ + _reset: function(){ + this._asserts = 0; + }, + + //------------------------------------------------------------------------- + // Generic Assertion Methods + //------------------------------------------------------------------------- + + /** + * Forces an assertion error to occur. + * @param {String} message (Optional) The message to display with the failure. + * @method fail + * @static + */ + fail : function (message) { + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Test force-failed.")); + }, + + //------------------------------------------------------------------------- + // Equality Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is equal to another. This uses the double equals sign + * so type cohersion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areEqual + * @static + */ + areEqual : function (expected, actual, message) { + YUITest.Assert._increment(); + if (expected != actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be equal."), expected, actual); + } + }, + + /** + * Asserts that a value is not equal to another. This uses the double equals sign + * so type cohersion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotEqual + * @static + */ + areNotEqual : function (unexpected, actual, + message) { + YUITest.Assert._increment(); + if (unexpected == actual) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be equal."), unexpected); + } + }, + + /** + * Asserts that a value is not the same as another. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotSame + * @static + */ + areNotSame : function (unexpected, actual, message) { + YUITest.Assert._increment(); + if (unexpected === actual) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be the same."), unexpected); + } + }, + + /** + * Asserts that a value is the same as another. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areSame + * @static + */ + areSame : function (expected, actual, message) { + YUITest.Assert._increment(); + if (expected !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be the same."), expected, actual); + } + }, + + //------------------------------------------------------------------------- + // Boolean Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is false. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFalse + * @static + */ + isFalse : function (actual, message) { + YUITest.Assert._increment(); + if (false !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be false."), false, actual); + } + }, + + /** + * Asserts that a value is true. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTrue + * @static + */ + isTrue : function (actual, message) { + YUITest.Assert._increment(); + if (true !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be true."), true, actual); + } + + }, + + //------------------------------------------------------------------------- + // Special Value Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is not a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNaN + * @static + */ + isNaN : function (actual, message){ + YUITest.Assert._increment(); + if (!isNaN(actual)){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be NaN."), NaN, actual); + } + }, + + /** + * Asserts that a value is not the special NaN value. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNaN + * @static + */ + isNotNaN : function (actual, message){ + YUITest.Assert._increment(); + if (isNaN(actual)){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be NaN."), NaN); + } + }, + + /** + * Asserts that a value is not null. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNull + * @static + */ + isNotNull : function (actual, message) { + YUITest.Assert._increment(); + if (actual === null) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be null."), null); + } + }, + + /** + * Asserts that a value is not undefined. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotUndefined + * @static + */ + isNotUndefined : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual == "undefined") { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should not be undefined."), undefined); + } + }, + + /** + * Asserts that a value is null. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNull + * @static + */ + isNull : function (actual, message) { + YUITest.Assert._increment(); + if (actual !== null) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be null."), null, actual); + } + }, + + /** + * Asserts that a value is undefined. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isUndefined + * @static + */ + isUndefined : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "undefined") { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be undefined."), undefined, actual); + } + }, + + //-------------------------------------------------------------------------- + // Instance Assertion Methods + //-------------------------------------------------------------------------- + + /** + * Asserts that a value is an array. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isArray + * @static + */ + isArray : function (actual, message) { + YUITest.Assert._increment(); + var shouldFail = false; + if (Array.isArray){ + shouldFail = !Array.isArray(actual); + } else { + shouldFail = Object.prototype.toString.call(actual) != "[object Array]"; + } + if (shouldFail){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be an array."), actual); + } + }, + + /** + * Asserts that a value is a Boolean. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isBoolean + * @static + */ + isBoolean : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "boolean"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a Boolean."), actual); + } + }, + + /** + * Asserts that a value is a function. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFunction + * @static + */ + isFunction : function (actual, message) { + YUITest.Assert._increment(); + if (!(actual instanceof Function)){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a function."), actual); + } + }, + + /** + * Asserts that a value is an instance of a particular object. This may return + * incorrect results when comparing objects from one frame to constructors in + * another frame. For best results, don't use in a cross-frame manner. + * @param {Function} expected The function that the object should be an instance of. + * @param {Object} actual The object to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isInstanceOf + * @static + */ + isInstanceOf : function (expected, actual, message) { + YUITest.Assert._increment(); + if (!(actual instanceof expected)){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value isn't an instance of expected type."), expected, actual); + } + }, + + /** + * Asserts that a value is a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNumber + * @static + */ + isNumber : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "number"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a number."), actual); + } + }, + + /** + * Asserts that a value is an object. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isObject + * @static + */ + isObject : function (actual, message) { + YUITest.Assert._increment(); + if (!actual || (typeof actual != "object" && typeof actual != "function")){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be an object."), actual); + } + }, + + /** + * Asserts that a value is a string. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isString + * @static + */ + isString : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "string"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a string."), actual); + } + }, + + /** + * Asserts that a value is of a particular type. + * @param {String} expectedType The expected type of the variable. + * @param {Object} actualValue The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTypeOf + * @static + */ + isTypeOf : function (expectedType, actualValue, message){ + YUITest.Assert._increment(); + if (typeof actualValue != expectedType){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be of type " + expectedType + "."), expectedType, typeof actualValue); + } + }, + + //-------------------------------------------------------------------------- + // Error Detection Methods + //-------------------------------------------------------------------------- + + /** + * Asserts that executing a particular method should throw an error of + * a specific type. This is a replacement for _should.error. + * @param {String|Function|Object} expectedError If a string, this + * is the error message that the error must have; if a function, this + * is the constructor that should have been used to create the thrown + * error; if an object, this is an instance of a particular error type + * with a specific error message (both must match). + * @param {Function} method The method to execute that should throw the error. + * @param {String} message (Optional) The message to display if the assertion + * fails. + * @method throwsError + * @return {void} + * @static + */ + throwsError: function(expectedError, method, message){ + YUITest.Assert._increment(); + var error = false; + + try { + method(); + } catch (thrown) { + + //check to see what type of data we have + if (typeof expectedError == "string"){ + + //if it's a string, check the error message + if (thrown.message != expectedError){ + error = true; + } + } else if (typeof expectedError == "function"){ + + //if it's a function, see if the error is an instance of it + if (!(thrown instanceof expectedError)){ + error = true; + } + + } else if (typeof expectedError == "object" && expectedError !== null){ + + //if it's an object, check the instance and message + if (!(thrown instanceof expectedError.constructor) || + thrown.message != expectedError.message){ + error = true; + } + + } else { //if it gets here, the argument could be wrong + error = true; + } + + if (error){ + throw new YUITest.UnexpectedError(thrown); + } else { + return; + } + } + + //if it reaches here, the error wasn't thrown, which is a bad thing + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Error should have been thrown.")); + } + +}; + + +/** + * The ArrayAssert object provides functions to test JavaScript array objects + * for a variety of cases. + * @namespace YUITest + * @class ArrayAssert + * @static + */ + +YUITest.ArrayAssert = { + + //========================================================================= + // Private methods + //========================================================================= + + /** + * Simple indexOf() implementation for an array. Defers to native + * if available. + * @param {Array} haystack The array to search. + * @param {Variant} needle The value to locate. + * @return {int} The index of the needle if found or -1 if not. + * @method _indexOf + * @private + */ + _indexOf: function(haystack, needle){ + if (haystack.indexOf){ + return haystack.indexOf(needle); + } else { + for (var i=0; i < haystack.length; i++){ + if (haystack[i] === needle){ + return i; + } + } + return -1; + } + }, + + /** + * Simple some() implementation for an array. Defers to native + * if available. + * @param {Array} haystack The array to search. + * @param {Function} matcher The function to run on each value. + * @return {Boolean} True if any value, when run through the matcher, + * returns true. + * @method _some + * @private + */ + _some: function(haystack, matcher){ + if (haystack.some){ + return haystack.some(matcher); + } else { + for (var i=0; i < haystack.length; i++){ + if (matcher(haystack[i])){ + return true; + } + } + return false; + } + }, + + /** + * Asserts that a value is present in an array. This uses the triple equals + * sign so no type cohersion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method contains + * @static + */ + contains : function (needle, haystack, + message) { + + YUITest.Assert._increment(); + + if (this._indexOf(haystack, needle) == -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are present in an array. This uses the triple equals + * sign so no type cohersion may occur. For this assertion to pass, all values must + * be found. + * @param {Object[]} needles An array of values that are expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsItems + * @static + */ + containsItems : function (needles, haystack, + message) { + YUITest.Assert._increment(); + + //begin checking values + for (var i=0; i < needles.length; i++){ + if (this._indexOf(haystack, needles[i]) == -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value " + needles[i] + " (" + (typeof needles[i]) + ") not found in array [" + haystack + "].")); + } + } + }, + + /** + * Asserts that a value matching some condition is present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the items matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsMatch + * @static + */ + containsMatch : function (matcher, haystack, + message) { + + YUITest.Assert._increment(); + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function."); + } + + if (!this._some(haystack, matcher)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "No match found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a value is not present in an array. This uses the triple equals + * Asserts that a value is not present in an array. This uses the triple equals + * sign so no type cohersion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContain + * @static + */ + doesNotContain : function (needle, haystack, + message) { + + YUITest.Assert._increment(); + + if (this._indexOf(haystack, needle) > -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are not present in an array. This uses the triple equals + * sign so no type cohersion may occur. For this assertion to pass, all values must + * not be found. + * @param {Object[]} needles An array of values that are not expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainItems + * @static + */ + doesNotContainItems : function (needles, haystack, + message) { + + YUITest.Assert._increment(); + + for (var i=0; i < needles.length; i++){ + if (this._indexOf(haystack, needles[i]) > -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + } + + }, + + /** + * Asserts that no values matching a condition are present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the item matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainMatch + * @static + */ + doesNotContainMatch : function (matcher, haystack, + message) { + + YUITest.Assert._increment(); + + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function."); + } + + if (this._some(haystack, matcher)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index. + * This uses the triple equals sign so no type cohersion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method indexOf + * @static + */ + indexOf : function (needle, haystack, index, message) { + + YUITest.Assert._increment(); + + //try to find the value in the array + for (var i=0; i < haystack.length; i++){ + if (haystack[i] === needle){ + if (index != i){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); + } + return; + } + } + + //if it makes it here, it wasn't found at all + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "].")); + }, + + /** + * Asserts that the values in an array are equal, and in the same position, + * as values in another array. This uses the double equals sign + * so type cohersion may occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreEqual + * @static + */ + itemsAreEqual : function (expected, actual, + message) { + + YUITest.Assert._increment(); + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (expected[i] != actual[i]){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not equal."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that the values in an array are equivalent, and in the same position, + * as values in another array. This uses a function to determine if the values + * are equivalent. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {Function} comparator A function that returns true if the values are equivalent + * or false if not. + * @param {String} message (Optional) The message to display if the assertion fails. + * @return {Void} + * @method itemsAreEquivalent + * @static + */ + itemsAreEquivalent : function (expected, actual, + comparator, message) { + + YUITest.Assert._increment(); + + //make sure the comparator is valid + if (typeof comparator != "function"){ + throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function."); + } + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (!comparator(expected[i], actual[i])){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that an array is empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isEmpty + * @static + */ + isEmpty : function (actual, message) { + YUITest.Assert._increment(); + if (actual.length > 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should be empty.")); + } + }, + + /** + * Asserts that an array is not empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotEmpty + * @static + */ + isNotEmpty : function (actual, message) { + YUITest.Assert._increment(); + if (actual.length === 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should not be empty.")); + } + }, + + /** + * Asserts that the values in an array are the same, and in the same position, + * as values in another array. This uses the triple equals sign + * so no type cohersion will occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreSame + * @static + */ + itemsAreSame : function (expected, actual, + message) { + + YUITest.Assert._increment(); + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (expected[i] !== actual[i]){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not the same."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index, + * starting from the back of the array. + * This uses the triple equals sign so no type cohersion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method lastIndexOf + * @static + */ + lastIndexOf : function (needle, haystack, index, message) { + + //try to find the value in the array + for (var i=haystack.length; i >= 0; i--){ + if (haystack[i] === needle){ + if (index != i){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); + } + return; + } + } + + //if it makes it here, it wasn't found at all + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value doesn't exist in array.")); + } + +}; + + +/** + * The ObjectAssert object provides functions to test JavaScript objects + * for a variety of cases. + * @namespace YUITest + * @class ObjectAssert + * @static + */ +YUITest.ObjectAssert = { + + /** + * Asserts that an object has all of the same properties + * and property values as the other. + * @param {Object} expected The object with all expected properties and values. + * @param {Object} actual The object to inspect. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areEqual + * @static + * @deprecated + */ + areEqual: function(expected, actual, message) { + YUITest.Assert._increment(); + + var expectedKeys = YUITest.Object.keys(expected), + actualKeys = YUITest.Object.keys(actual); + + //first check keys array length + if (expectedKeys.length != actualKeys.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Object should have " + expectedKeys.length + " keys but has " + actualKeys.length)); + } + + //then check values + for (var name in expected){ + if (expected.hasOwnProperty(name)){ + if (expected[name] != actual[name]){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be equal for property " + name), expected[name], actual[name]); + } + } + } + }, + + /** + * Asserts that an object has a property with the given name. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasKey + * @static + * @deprecated Use ownsOrInheritsKey() instead + */ + hasKey: function (propertyName, object, message) { + YUITest.ObjectAssert.ownsOrInheritsKey(propertyName, object, message); + }, + + /** + * Asserts that an object has all properties of a reference object. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasKeys + * @static + * @deprecated Use ownsOrInheritsKeys() instead + */ + hasKeys: function (properties, object, message) { + YUITest.ObjectAssert.ownsOrInheritsKeys(properties, objects, message); + }, + + /** + * Asserts that a property with the given name exists on an object's prototype. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method inheritsKey + * @static + */ + inheritsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!(propertyName in object && !object.hasOwnProperty(propertyName))){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); + } + }, + + /** + * Asserts that all properties exist on an object prototype. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method inheritsKeys + * @static + */ + inheritsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!(propertyName in object && !object.hasOwnProperty(properties[i]))){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object instance.")); + } + } + }, + + /** + * Asserts that a property with the given name exists on an object instance (not on its prototype). + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsKey + * @static + */ + ownsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!object.hasOwnProperty(propertyName)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); + } + }, + + /** + * Asserts that all properties exist on an object instance (not on its prototype). + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsKeys + * @static + */ + ownsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!object.hasOwnProperty(properties[i])){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object instance.")); + } + } + }, + + /** + * Asserts that an object owns no properties. + * @param {Object} object The object to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsNoKeys + * @static + */ + ownsNoKeys : function (object, message) { + YUITest.Assert._increment(); + var count = 0, + name; + for (name in object){ + if (object.hasOwnProperty(name)){ + count++; + } + } + + if (count !== 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Object owns " + count + " properties but should own none.")); + } + + }, + + /** + * Asserts that an object has a property with the given name. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsOrInheritsKey + * @static + */ + ownsOrInheritsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!(propertyName in object)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object.")); + } + }, + + /** + * Asserts that an object has all properties of a reference object. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsOrInheritsKeys + * @static + */ + ownsOrInheritsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!(properties[i] in object)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object.")); + } + } + } +}; + + + +/** + * The DateAssert object provides functions to test JavaScript Date objects + * for a variety of cases. + * @namespace YUITest + * @class DateAssert + * @static + */ + +YUITest.DateAssert = { + + /** + * Asserts that a date's month, day, and year are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method datesAreEqual + * @static + */ + datesAreEqual : function (expected, actual, message){ + YUITest.Assert._increment(); + if (expected instanceof Date && actual instanceof Date){ + var msg = ""; + + //check years first + if (expected.getFullYear() != actual.getFullYear()){ + msg = "Years should be equal."; + } + + //now check months + if (expected.getMonth() != actual.getMonth()){ + msg = "Months should be equal."; + } + + //last, check the day of the month + if (expected.getDate() != actual.getDate()){ + msg = "Days of month should be equal."; + } + + if (msg.length){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual); + } + } else { + throw new TypeError("YUITest.DateAssert.datesAreEqual(): Expected and actual values must be Date objects."); + } + }, + + /** + * Asserts that a date's hour, minutes, and seconds are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method timesAreEqual + * @static + */ + timesAreEqual : function (expected, actual, message){ + YUITest.Assert._increment(); + if (expected instanceof Date && actual instanceof Date){ + var msg = ""; + + //check hours first + if (expected.getHours() != actual.getHours()){ + msg = "Hours should be equal."; + } + + //now check minutes + if (expected.getMinutes() != actual.getMinutes()){ + msg = "Minutes should be equal."; + } + + //last, check the seconds + if (expected.getSeconds() != actual.getSeconds()){ + msg = "Seconds should be equal."; + } + + if (msg.length){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual); + } + } else { + throw new TypeError("YUITest.DateAssert.timesAreEqual(): Expected and actual values must be Date objects."); + } + } + +}; + +/** + * Creates a new mock object. + * @namespace YUITest + * @class Mock + * @constructor + * @param {Object} template (Optional) An object whose methods + * should be stubbed out on the mock object. + */ +YUITest.Mock = function(template){ + + //use blank object is nothing is passed in + template = template || {}; + + var mock, + name; + + //try to create mock that keeps prototype chain intact + //fails in the case of ActiveX objects + try { + function f(){} + f.prototype = template; + mock = new f(); + } catch (ex) { + mock = {}; + } + + //create stubs for all methods + for (name in template){ + if (template.hasOwnProperty(name)){ + if (typeof template[name] == "function"){ + mock[name] = function(name){ + return function(){ + YUITest.Assert.fail("Method " + name + "() was called but was not expected to be."); + }; + }(name); + } + } + } + + //return it + return mock; +}; + +/** + * Assigns an expectation to a mock object. This is used to create + * methods and properties on the mock object that are monitored for + * calls and changes, respectively. + * @param {Object} mock The object to add the expectation to. + * @param {Object} expectation An object defining the expectation. For + * a method, the keys "method" and "args" are required with + * an optional "returns" key available. For properties, the keys + * "property" and "value" are required. + * @return {void} + * @method expect + * @static + */ +YUITest.Mock.expect = function(mock /*:Object*/, expectation /*:Object*/){ + + //make sure there's a place to store the expectations + if (!mock.__expectations) { + mock.__expectations = {}; + } + + //method expectation + if (expectation.method){ + var name = expectation.method, + args = expectation.args || [], + result = expectation.returns, + callCount = (typeof expectation.callCount == "number") ? expectation.callCount : 1, + error = expectation.error, + run = expectation.run || function(){}, + i; + + //save expectations + mock.__expectations[name] = expectation; + expectation.callCount = callCount; + expectation.actualCallCount = 0; + + //process arguments + for (i=0; i < args.length; i++){ + if (!(args[i] instanceof YUITest.Mock.Value)){ + args[i] = YUITest.Mock.Value(YUITest.Assert.areSame, [args[i]], "Argument " + i + " of " + name + "() is incorrect."); + } + } + + //if the method is expected to be called + if (callCount > 0){ + mock[name] = function(){ + try { + expectation.actualCallCount++; + YUITest.Assert.areEqual(args.length, arguments.length, "Method " + name + "() passed incorrect number of arguments."); + for (var i=0, len=args.length; i < len; i++){ + args[i].verify(arguments[i]); + } + + run.apply(this, arguments); + + if (error){ + throw error; + } + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } + + return result; + }; + } else { + + //method should fail if called when not expected + mock[name] = function(){ + try { + YUITest.Assert.fail("Method " + name + "() should not have been called."); + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } + }; + } + } else if (expectation.property){ + //save expectations + mock.__expectations[name] = expectation; + } +}; + +/** + * Verifies that all expectations of a mock object have been met and + * throws an assertion error if not. + * @param {Object} mock The object to verify.. + * @return {void} + * @method verify + * @static + */ +YUITest.Mock.verify = function(mock){ + try { + + for (var name in mock.__expectations){ + if (mock.__expectations.hasOwnProperty(name)){ + var expectation = mock.__expectations[name]; + if (expectation.method) { + YUITest.Assert.areEqual(expectation.callCount, expectation.actualCallCount, "Method " + expectation.method + "() wasn't called the expected number of times."); + } else if (expectation.property){ + YUITest.Assert.areEqual(expectation.value, mock[expectation.property], "Property " + expectation.property + " wasn't set to the correct value."); + } + } + } + + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } +}; + +/** + * Creates a new value matcher. + * @param {Function} method The function to call on the value. + * @param {Array} originalArgs (Optional) Array of arguments to pass to the method. + * @param {String} message (Optional) Message to display in case of failure. + * @namespace YUITest.Mock + * @class Value + * @constructor + */ +YUITest.Mock.Value = function(method, originalArgs, message){ + if (this instanceof YUITest.Mock.Value){ + this.verify = function(value){ + var args = [].concat(originalArgs || []); + args.push(value); + args.push(message); + method.apply(null, args); + }; + } else { + return new YUITest.Mock.Value(method, originalArgs, message); + } +}; + +/** + * Predefined matcher to match any value. + * @property Any + * @static + * @type Function + */ +YUITest.Mock.Value.Any = YUITest.Mock.Value(function(){}); + +/** + * Predefined matcher to match boolean values. + * @property Boolean + * @static + * @type Function + */ +YUITest.Mock.Value.Boolean = YUITest.Mock.Value(YUITest.Assert.isBoolean); + +/** + * Predefined matcher to match number values. + * @property Number + * @static + * @type Function + */ +YUITest.Mock.Value.Number = YUITest.Mock.Value(YUITest.Assert.isNumber); + +/** + * Predefined matcher to match string values. + * @property String + * @static + * @type Function + */ +YUITest.Mock.Value.String = YUITest.Mock.Value(YUITest.Assert.isString); + +/** + * Predefined matcher to match object values. + * @property Object + * @static + * @type Function + */ +YUITest.Mock.Value.Object = YUITest.Mock.Value(YUITest.Assert.isObject); + +/** + * Predefined matcher to match function values. + * @property Function + * @static + * @type Function + */ +YUITest.Mock.Value.Function = YUITest.Mock.Value(YUITest.Assert.isFunction); + +/** + * Convenience type for storing and aggregating + * test result information. + * @private + * @namespace YUITest + * @class Results + * @constructor + * @param {String} name The name of the test. + */ +YUITest.Results = function(name){ + + /** + * Name of the test, test case, or test suite. + * @type String + * @property name + */ + this.name = name; + + /** + * Number of passed tests. + * @type int + * @property passed + */ + this.passed = 0; + + /** + * Number of failed tests. + * @type int + * @property failed + */ + this.failed = 0; + + /** + * Number of errors that occur in non-test methods. + * @type int + * @property errors + */ + this.errors = 0; + + /** + * Number of ignored tests. + * @type int + * @property ignored + */ + this.ignored = 0; + + /** + * Number of total tests. + * @type int + * @property total + */ + this.total = 0; + + /** + * Amount of time (ms) it took to complete testing. + * @type int + * @property duration + */ + this.duration = 0; +} + +/** + * Includes results from another results object into this one. + * @param {YUITest.Results} result The results object to include. + * @method include + * @return {void} + */ +YUITest.Results.prototype.include = function(results){ + this.passed += results.passed; + this.failed += results.failed; + this.ignored += results.ignored; + this.total += results.total; + this.errors += results.errors; +}; + +/** + * Test case containing various tests to run. + * @param template An object containing any number of test methods, other methods, + * an optional name, and anything else the test case needs. + * @class TestCase + * @namespace YUITest + * @constructor + */ +YUITest.TestCase = function (template) { + + /** + * Special rules for the test case. Possible subobjects + * are fail, for tests that should fail, and error, for + * tests that should throw an error. + */ + this._should = {}; + + //copy over all properties from the template to this object + for (var prop in template) { + this[prop] = template[prop]; + } + + //check for a valid name + if (typeof this.name != "string"){ + this.name = "testCase" + (+new Date()); + } + +}; + +YUITest.TestCase.prototype = { + + //restore constructor + constructor: YUITest.TestCase, + + /** + * Method to call from an async init method to + * restart the test case. When called, returns a function + * that should be called when tests are ready to continue. + * @method callback + * @return {Function} The function to call as a callback. + */ + callback: function(){ + return YUITest.TestRunner.callback.apply(YUITest.TestRunner,arguments); + }, + + /** + * Resumes a paused test and runs the given function. + * @param {Function} segment (Optional) The function to run. + * If omitted, the test automatically passes. + * @return {Void} + * @method resume + */ + resume : function (segment) { + YUITest.TestRunner.resume(segment); + }, + + /** + * Causes the test case to wait a specified amount of time and then + * continue executing the given code. + * @param {Function} segment (Optional) The function to run after the delay. + * If omitted, the TestRunner will wait until resume() is called. + * @param {int} delay (Optional) The number of milliseconds to wait before running + * the function. If omitted, defaults to zero. + * @return {Void} + * @method wait + */ + wait : function (segment, delay){ + + var actualDelay = (typeof segment == "number" ? segment : delay); + actualDelay = (typeof actualDelay == "number" ? actualDelay : 10000); + + if (typeof segment == "function"){ + throw new YUITest.Wait(segment, actualDelay); + } else { + throw new YUITest.Wait(function(){ + YUITest.Assert.fail("Timeout: wait() called but resume() never called."); + }, actualDelay); + } + }, + + //------------------------------------------------------------------------- + // Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a given condition is true. If not, then a YUITest.AssertionError object is thrown + * and the test fails. + * @method assert + * @param {Boolean} condition The condition to test. + * @param {String} message The message to display if the assertion fails. + */ + assert : function (condition, message){ + YUITest.Assert._increment(); + if (!condition){ + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Assertion failed.")); + } + }, + + /** + * Forces an assertion error to occur. Shortcut for YUITest.Assert.fail(). + * @method fail + * @param {String} message (Optional) The message to display with the failure. + */ + fail: function (message) { + YUITest.Assert.fail(message); + }, + + //------------------------------------------------------------------------- + // Stub Methods + //------------------------------------------------------------------------- + + /** + * Function to run once before tests start to run. + * This executes before the first call to setUp(). + */ + init: function(){ + //noop + }, + + /** + * Function to run once after tests finish running. + * This executes after the last call to tearDown(). + */ + destroy: function(){ + //noop + }, + + /** + * Function to run before each test is executed. + * @return {Void} + * @method setUp + */ + setUp : function () { + //noop + }, + + /** + * Function to run after each test is executed. + * @return {Void} + * @method tearDown + */ + tearDown: function () { + //noop + } +}; + + + +/** + * A test suite that can contain a collection of TestCase and TestSuite objects. + * @param {String||Object} data The name of the test suite or an object containing + * a name property as well as setUp and tearDown methods. + * @namespace YUITest + * @class TestSuite + * @constructor + */ +YUITest.TestSuite = function (data) { + + /** + * The name of the test suite. + * @type String + * @property name + */ + this.name = ""; + + /** + * Array of test suites and test cases. + * @type Array + * @property items + * @private + */ + this.items = []; + + //initialize the properties + if (typeof data == "string"){ + this.name = data; + } else if (data instanceof Object){ + for (var prop in data){ + if (data.hasOwnProperty(prop)){ + this[prop] = data[prop]; + } + } + } + + //double-check name + if (this.name === ""){ + this.name = "testSuite" + (+new Date()); + } + +}; + +YUITest.TestSuite.prototype = { + + //restore constructor + constructor: YUITest.TestSuite, + + /** + * Adds a test suite or test case to the test suite. + * @param {YUITest.TestSuite||YUITest.TestCase} testObject The test suite or test case to add. + * @return {Void} + * @method add + */ + add : function (testObject) { + if (testObject instanceof YUITest.TestSuite || testObject instanceof YUITest.TestCase) { + this.items.push(testObject); + } + return this; + }, + + //------------------------------------------------------------------------- + // Stub Methods + //------------------------------------------------------------------------- + + /** + * Function to run before each test is executed. + * @return {Void} + * @method setUp + */ + setUp : function () { + }, + + /** + * Function to run after each test is executed. + * @return {Void} + * @method tearDown + */ + tearDown: function () { + } + +}; + +/** + * An object object containing test result formatting methods. + * @namespace YUITest + * @class TestFormat + * @static + */ +YUITest.TestFormat = function(){ + + /* (intentionally not documented) + * Basic XML escaping method. Replaces quotes, less-than, greater-than, + * apostrophe, and ampersand characters with their corresponding entities. + * @param {String} text The text to encode. + * @return {String} The XML-escaped text. + */ + function xmlEscape(text){ + + return text.replace(/[<>"'&]/g, function(value){ + switch(value){ + case "<": return "<"; + case ">": return ">"; + case "\"": return """; + case "'": return "'"; + case "&": return "&"; + } + }); + + } + + + return { + + /** + * Returns test results formatted as a JSON string. Requires JSON utility. + * @param {Object} result The results object created by TestRunner. + * @return {String} A JSON-formatted string of results. + * @method JSON + * @static + */ + JSON: function(results) { + return YUITest.Util.JSON.stringify(results); + }, + + /** + * Returns test results formatted as an XML string. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @method XML + * @static + */ + XML: function(results) { + + function serializeToXML(results){ + var xml = "<" + results.type + " name=\"" + xmlEscape(results.name) + "\""; + + if (typeof(results.duration)=="number"){ + xml += " duration=\"" + results.duration + "\""; + } + + if (results.type == "test"){ + xml += " result=\"" + results.result + "\" message=\"" + xmlEscape(results.message) + "\">"; + } else { + xml += " passed=\"" + results.passed + "\" failed=\"" + results.failed + "\" ignored=\"" + results.ignored + "\" total=\"" + results.total + "\">"; + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToXML(results[prop]); + } + } + } + } + + xml += ""; + + return xml; + } + + return "" + serializeToXML(results); + + }, + + + /** + * Returns test results formatted in JUnit XML format. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @method JUnitXML + * @static + */ + JUnitXML: function(results) { + + function serializeToJUnitXML(results){ + var xml = ""; + + switch (results.type){ + //equivalent to testcase in JUnit + case "test": + if (results.result != "ignore"){ + xml = ""; + if (results.result == "fail"){ + xml += ""; + } + xml+= ""; + } + break; + + //equivalent to testsuite in JUnit + case "testcase": + + xml = ""; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + + xml += ""; + break; + + //no JUnit equivalent, don't output anything + case "testsuite": + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + break; + + //top-level, equivalent to testsuites in JUnit + case "report": + + xml = ""; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + + xml += ""; + + //no default + } + + return xml; + + } + + return "" + serializeToJUnitXML(results); + }, + + /** + * Returns test results formatted in TAP format. + * For more information, see
Test Anything Protocol. + * @param {Object} result The results object created by TestRunner. + * @return {String} A TAP-formatted string of results. + * @method TAP + * @static + */ + TAP: function(results) { + + var currentTestNum = 1; + + function serializeToTAP(results){ + var text = ""; + + switch (results.type){ + + case "test": + if (results.result != "ignore"){ + + text = "ok " + (currentTestNum++) + " - " + results.name; + + if (results.result == "fail"){ + text = "not " + text + " - " + results.message; + } + + text += "\n"; + } else { + text = "#Ignored test " + results.name + "\n"; + } + break; + + case "testcase": + + text = "#Begin testcase " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + text += "#End testcase " + results.name + "\n"; + + + break; + + case "testsuite": + + text = "#Begin testsuite " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + text += "#End testsuite " + results.name + "\n"; + break; + + case "report": + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + //no default + } + + return text; + + } + + return "1.." + results.total + "\n" + serializeToTAP(results); + } + + }; +}(); + +/** + * An object object containing coverage result formatting methods. + * @namespace YUITest + * @class CoverageFormat + * @static + */ +YUITest.CoverageFormat = { + + /** + * Returns the coverage report in JSON format. This is the straight + * JSON representation of the native coverage report. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method JSON + * @namespace YUITest.CoverageFormat + */ + JSON: function(coverage){ + return YUITest.Util.JSON.stringify(coverage); + }, + + /** + * Returns the coverage report in a JSON format compatible with + * Xdebug. See Xdebug Documentation + * for more information. Note: function coverage is not available + * in this format. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method XdebugJSON + * @namespace YUITest.CoverageFormat + */ + XdebugJSON: function(coverage){ + + var report = {}; + for (var prop in coverage){ + if (coverage.hasOwnProperty(prop)){ + report[prop] = coverage[prop].lines; + } + } + + return YUITest.Util.JSON.stringify(coverage); + } + +}; + + + /** + * Runs test suites and test cases, providing events to allowing for the + * interpretation of test results. + * @namespace YUITest + * @class TestRunner + * @static + */ + YUITest.TestRunner = function(){ + + /*(intentionally not documented) + * Determines if any of the array of test groups appears + * in the given TestRunner filter. + * @param {Array} testGroups The array of test groups to + * search for. + * @param {String} filter The TestRunner groups filter. + */ + function inGroups(testGroups, filter){ + if (!filter.length){ + return true; + } else { + if (testGroups){ + for (var i=0, len=testGroups.length; i < len; i++){ + if (filter.indexOf("," + testGroups[i] + ",") > -1){ + return true; + } + } + } + return false; + } + } + + /** + * A node in the test tree structure. May represent a TestSuite, TestCase, or + * test function. + * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function. + * @class TestNode + * @constructor + * @private + */ + function TestNode(testObject){ + + /** + * The TestSuite, TestCase, or test function represented by this node. + * @type Variant + * @property testObject + */ + this.testObject = testObject; + + /** + * Pointer to this node's first child. + * @type TestNode + * @property firstChild + */ + this.firstChild = null; + + /** + * Pointer to this node's last child. + * @type TestNode + * @property lastChild + */ + this.lastChild = null; + + /** + * Pointer to this node's parent. + * @type TestNode + * @property parent + */ + this.parent = null; + + /** + * Pointer to this node's next sibling. + * @type TestNode + * @property next + */ + this.next = null; + + /** + * Test results for this test object. + * @type object + * @property results + */ + this.results = new YUITest.Results(); + + //initialize results + if (testObject instanceof YUITest.TestSuite){ + this.results.type = "testsuite"; + this.results.name = testObject.name; + } else if (testObject instanceof YUITest.TestCase){ + this.results.type = "testcase"; + this.results.name = testObject.name; + } + + } + + TestNode.prototype = { + + /** + * Appends a new test object (TestSuite, TestCase, or test function name) as a child + * of this node. + * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function. + * @return {Void} + */ + appendChild : function (testObject){ + var node = new TestNode(testObject); + if (this.firstChild === null){ + this.firstChild = this.lastChild = node; + } else { + this.lastChild.next = node; + this.lastChild = node; + } + node.parent = this; + return node; + } + }; + + /** + * Runs test suites and test cases, providing events to allowing for the + * interpretation of test results. + * @namespace Test + * @class Runner + * @static + */ + function TestRunner(){ + + //inherit from EventTarget + YUITest.EventTarget.call(this); + + /** + * Suite on which to attach all TestSuites and TestCases to be run. + * @type YUITest.TestSuite + * @property masterSuite + * @static + * @private + */ + this.masterSuite = new YUITest.TestSuite("yuitests" + (new Date()).getTime()); + + /** + * Pointer to the current node in the test tree. + * @type TestNode + * @private + * @property _cur + * @static + */ + this._cur = null; + + /** + * Pointer to the root node in the test tree. + * @type TestNode + * @private + * @property _root + * @static + */ + this._root = null; + + /** + * Indicates if the TestRunner will log events or not. + * @type Boolean + * @property _log + * @private + * @static + */ + this._log = true; + + /** + * Indicates if the TestRunner is waiting as a result of + * wait() being called. + * @type Boolean + * @property _waiting + * @private + * @static + */ + this._waiting = false; + + /** + * Indicates if the TestRunner is currently running tests. + * @type Boolean + * @private + * @property _running + * @static + */ + this._running = false; + + /** + * Holds copy of the results object generated when all tests are + * complete. + * @type Object + * @private + * @property _lastResults + * @static + */ + this._lastResults = null; + + /** + * Data object that is passed around from method to method. + * @type Object + * @private + * @property _data + * @static + */ + this._context = null; + + /** + * The list of test groups to run. The list is represented + * by a comma delimited string with commas at the start and + * end. + * @type String + * @private + * @property _groups + * @static + */ + this._groups = ""; + } + + TestRunner.prototype = YUITest.Util.mix(new YUITest.EventTarget(), { + + //restore prototype + constructor: YUITest.TestRunner, + + //------------------------------------------------------------------------- + // Constants + //------------------------------------------------------------------------- + + /** + * Fires when a test case is opened but before the first + * test is executed. + * @event testcasebegin + * @static + */ + TEST_CASE_BEGIN_EVENT : "testcasebegin", + + /** + * Fires when all tests in a test case have been executed. + * @event testcasecomplete + * @static + */ + TEST_CASE_COMPLETE_EVENT : "testcasecomplete", + + /** + * Fires when a test suite is opened but before the first + * test is executed. + * @event testsuitebegin + * @static + */ + TEST_SUITE_BEGIN_EVENT : "testsuitebegin", + + /** + * Fires when all test cases in a test suite have been + * completed. + * @event testsuitecomplete + * @static + */ + TEST_SUITE_COMPLETE_EVENT : "testsuitecomplete", + + /** + * Fires when a test has passed. + * @event pass + * @static + */ + TEST_PASS_EVENT : "pass", + + /** + * Fires when a test has failed. + * @event fail + * @static + */ + TEST_FAIL_EVENT : "fail", + + /** + * Fires when a non-test method has an error. + * @event error + * @static + */ + ERROR_EVENT : "error", + + /** + * Fires when a test has been ignored. + * @event ignore + * @static + */ + TEST_IGNORE_EVENT : "ignore", + + /** + * Fires when all test suites and test cases have been completed. + * @event complete + * @static + */ + COMPLETE_EVENT : "complete", + + /** + * Fires when the run() method is called. + * @event begin + * @static + */ + BEGIN_EVENT : "begin", + + //------------------------------------------------------------------------- + // Test Tree-Related Methods + //------------------------------------------------------------------------- + + /** + * Adds a test case to the test tree as a child of the specified node. + * @param {TestNode} parentNode The node to add the test case to as a child. + * @param {YUITest.TestCase} testCase The test case to add. + * @return {Void} + * @static + * @private + * @method _addTestCaseToTestTree + */ + _addTestCaseToTestTree : function (parentNode, testCase){ + + //add the test suite + var node = parentNode.appendChild(testCase), + prop, + testName; + + //iterate over the items in the test case + for (prop in testCase){ + if ((prop.indexOf("test") === 0 || prop.indexOf(" ") > -1) && typeof testCase[prop] == "function"){ + node.appendChild(prop); + } + } + + }, + + /** + * Adds a test suite to the test tree as a child of the specified node. + * @param {TestNode} parentNode The node to add the test suite to as a child. + * @param {YUITest.TestSuite} testSuite The test suite to add. + * @return {Void} + * @static + * @private + * @method _addTestSuiteToTestTree + */ + _addTestSuiteToTestTree : function (parentNode, testSuite) { + + //add the test suite + var node = parentNode.appendChild(testSuite); + + //iterate over the items in the master suite + for (var i=0; i < testSuite.items.length; i++){ + if (testSuite.items[i] instanceof YUITest.TestSuite) { + this._addTestSuiteToTestTree(node, testSuite.items[i]); + } else if (testSuite.items[i] instanceof YUITest.TestCase) { + this._addTestCaseToTestTree(node, testSuite.items[i]); + } + } + }, + + /** + * Builds the test tree based on items in the master suite. The tree is a hierarchical + * representation of the test suites, test cases, and test functions. The resulting tree + * is stored in _root and the pointer _cur is set to the root initially. + * @return {Void} + * @static + * @private + * @method _buildTestTree + */ + _buildTestTree : function () { + + this._root = new TestNode(this.masterSuite); + //this._cur = this._root; + + //iterate over the items in the master suite + for (var i=0; i < this.masterSuite.items.length; i++){ + if (this.masterSuite.items[i] instanceof YUITest.TestSuite) { + this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]); + } else if (this.masterSuite.items[i] instanceof YUITest.TestCase) { + this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]); + } + } + + }, + + //------------------------------------------------------------------------- + // Private Methods + //------------------------------------------------------------------------- + + /** + * Handles the completion of a test object's tests. Tallies test results + * from one level up to the next. + * @param {TestNode} node The TestNode representing the test object. + * @return {Void} + * @method _handleTestObjectComplete + * @private + */ + _handleTestObjectComplete : function (node) { + var parentNode; + + if (typeof node.testObject == "object" && node !== null){ + parentNode = node.parent; + + if (parentNode){ + parentNode.results.include(node.results); + parentNode.results[node.testObject.name] = node.results; + } + + if (node.testObject instanceof YUITest.TestSuite){ + this._execNonTestMethod(node, "tearDown", false); + node.results.duration = (new Date()) - node._start; + this.fire({ type: this.TEST_SUITE_COMPLETE_EVENT, testSuite: node.testObject, results: node.results}); + } else if (node.testObject instanceof YUITest.TestCase){ + this._execNonTestMethod(node, "destroy", false); + node.results.duration = (new Date()) - node._start; + this.fire({ type: this.TEST_CASE_COMPLETE_EVENT, testCase: node.testObject, results: node.results}); + } + } + }, + + //------------------------------------------------------------------------- + // Navigation Methods + //------------------------------------------------------------------------- + + /** + * Retrieves the next node in the test tree. + * @return {TestNode} The next node in the test tree or null if the end is reached. + * @private + * @static + * @method _next + */ + _next : function () { + + if (this._cur === null){ + this._cur = this._root; + } else if (this._cur.firstChild) { + this._cur = this._cur.firstChild; + } else if (this._cur.next) { + this._cur = this._cur.next; + } else { + while (this._cur && !this._cur.next && this._cur !== this._root){ + this._handleTestObjectComplete(this._cur); + this._cur = this._cur.parent; + } + + this._handleTestObjectComplete(this._cur); + + if (this._cur == this._root){ + this._cur.results.type = "report"; + this._cur.results.timestamp = (new Date()).toLocaleString(); + this._cur.results.duration = (new Date()) - this._cur._start; + this._lastResults = this._cur.results; + this._running = false; + this.fire({ type: this.COMPLETE_EVENT, results: this._lastResults}); + this._cur = null; + } else { + this._cur = this._cur.next; + } + } + + return this._cur; + }, + + /** + * Executes a non-test method (init, setUp, tearDown, destroy) + * and traps an errors. If an error occurs, an error event is + * fired. + * @param {Object} node The test node in the testing tree. + * @param {String} methodName The name of the method to execute. + * @param {Boolean} allowAsync Determines if the method can be called asynchronously. + * @return {Boolean} True if an async method was called, false if not. + * @method _execNonTestMethod + * @private + */ + _execNonTestMethod: function(node, methodName, allowAsync){ + var testObject = node.testObject, + event = { type: this.ERROR_EVENT }; + try { + if (allowAsync && testObject["async:" + methodName]){ + testObject["async:" + methodName](this._context); + return true; + } else { + testObject[methodName](this._context); + } + } catch (ex){ + node.results.errors++; + event.error = ex; + event.methodName = methodName; + if (testObject instanceof YUITest.TestCase){ + event.testCase = testObject; + } else { + event.testSuite = testSuite; + } + + this.fire(event); + } + + return false; + }, + + /** + * Runs a test case or test suite, returning the results. + * @param {YUITest.TestCase|YUITest.TestSuite} testObject The test case or test suite to run. + * @return {Object} Results of the execution with properties passed, failed, and total. + * @private + * @method _run + * @static + */ + _run : function () { + + //flag to indicate if the TestRunner should wait before continuing + var shouldWait = false; + + //get the next test node + var node = this._next(); + + if (node !== null) { + + //set flag to say the testrunner is running + this._running = true; + + //eliminate last results + this._lastResult = null; + + var testObject = node.testObject; + + //figure out what to do + if (typeof testObject == "object" && testObject !== null){ + if (testObject instanceof YUITest.TestSuite){ + this.fire({ type: this.TEST_SUITE_BEGIN_EVENT, testSuite: testObject }); + node._start = new Date(); + this._execNonTestMethod(node, "setUp" ,false); + } else if (testObject instanceof YUITest.TestCase){ + this.fire({ type: this.TEST_CASE_BEGIN_EVENT, testCase: testObject }); + node._start = new Date(); + + //regular or async init + /*try { + if (testObject["async:init"]){ + testObject["async:init"](this._context); + return; + } else { + testObject.init(this._context); + } + } catch (ex){ + node.results.errors++; + this.fire({ type: this.ERROR_EVENT, error: ex, testCase: testObject, methodName: "init" }); + }*/ + if(this._execNonTestMethod(node, "init", true)){ + return; + } + } + + //some environments don't support setTimeout + if (typeof setTimeout != "undefined"){ + setTimeout(function(){ + YUITest.TestRunner._run(); + }, 0); + } else { + this._run(); + } + } else { + this._runTest(node); + } + + } + }, + + _resumeTest : function (segment) { + + //get relevant information + var node = this._cur; + + //we know there's no more waiting now + this._waiting = false; + + //if there's no node, it probably means a wait() was called after resume() + if (!node){ + //TODO: Handle in some way? + //console.log("wait() called after resume()"); + //this.fire("error", { testCase: "(unknown)", test: "(unknown)", error: new Error("wait() called after resume()")} ); + return; + } + + var testName = node.testObject; + var testCase = node.parent.testObject; + + //cancel other waits if available + if (testCase.__yui_wait){ + clearTimeout(testCase.__yui_wait); + delete testCase.__yui_wait; + } + + //get the "should" test cases + var shouldFail = testName.indexOf("fail:") === 0 || + (testCase._should.fail || {})[testName]; + var shouldError = (testCase._should.error || {})[testName]; + + //variable to hold whether or not the test failed + var failed = false; + var error = null; + + //try the test + try { + + //run the test + segment.call(testCase, this._context); + + //if the test hasn't already failed and doesn't have any asserts... + if(YUITest.Assert._getCount() == 0){ + throw new YUITest.AssertionError("Test has no asserts."); + } + //if it should fail, and it got here, then it's a fail because it didn't + else if (shouldFail){ + error = new YUITest.ShouldFail(); + failed = true; + } else if (shouldError){ + error = new YUITest.ShouldError(); + failed = true; + } + + } catch (thrown){ + + //cancel any pending waits, the test already failed + if (testCase.__yui_wait){ + clearTimeout(testCase.__yui_wait); + delete testCase.__yui_wait; + } + + //figure out what type of error it was + if (thrown instanceof YUITest.AssertionError) { + if (!shouldFail){ + error = thrown; + failed = true; + } + } else if (thrown instanceof YUITest.Wait){ + + if (typeof thrown.segment == "function"){ + if (typeof thrown.delay == "number"){ + + //some environments don't support setTimeout + if (typeof setTimeout != "undefined"){ + testCase.__yui_wait = setTimeout(function(){ + YUITest.TestRunner._resumeTest(thrown.segment); + }, thrown.delay); + this._waiting = true; + } else { + throw new Error("Asynchronous tests not supported in this environment."); + } + } + } + + return; + + } else { + //first check to see if it should error + if (!shouldError) { + error = new YUITest.UnexpectedError(thrown); + failed = true; + } else { + //check to see what type of data we have + if (typeof shouldError == "string"){ + + //if it's a string, check the error message + if (thrown.message != shouldError){ + error = new YUITest.UnexpectedError(thrown); + failed = true; + } + } else if (typeof shouldError == "function"){ + + //if it's a function, see if the error is an instance of it + if (!(thrown instanceof shouldError)){ + error = new YUITest.UnexpectedError(thrown); + failed = true; + } + + } else if (typeof shouldError == "object" && shouldError !== null){ + + //if it's an object, check the instance and message + if (!(thrown instanceof shouldError.constructor) || + thrown.message != shouldError.message){ + error = new YUITest.UnexpectedError(thrown); + failed = true; + } + + } + + } + } + + } + + //fire appropriate event + if (failed) { + this.fire({ type: this.TEST_FAIL_EVENT, testCase: testCase, testName: testName, error: error }); + } else { + this.fire({ type: this.TEST_PASS_EVENT, testCase: testCase, testName: testName }); + } + + //run the tear down + this._execNonTestMethod(node.parent, "tearDown", false); + + //reset the assert count + YUITest.Assert._reset(); + + //calculate duration + var duration = (new Date()) - node._start; + + //update results + node.parent.results[testName] = { + result: failed ? "fail" : "pass", + message: error ? error.getMessage() : "Test passed", + type: "test", + name: testName, + duration: duration + }; + + if (failed){ + node.parent.results.failed++; + } else { + node.parent.results.passed++; + } + node.parent.results.total++; + + //set timeout not supported in all environments + if (typeof setTimeout != "undefined"){ + setTimeout(function(){ + YUITest.TestRunner._run(); + }, 0); + } else { + this._run(); + } + + }, + + /** + * Handles an error as if it occurred within the currently executing + * test. This is for mock methods that may be called asynchronously + * and therefore out of the scope of the TestRunner. Previously, this + * error would bubble up to the browser. Now, this method is used + * to tell TestRunner about the error. This should never be called + * by anyplace other than the Mock object. + * @param {Error} error The error object. + * @return {Void} + * @method _handleError + * @private + * @static + */ + _handleError: function(error){ + + if (this._waiting){ + this._resumeTest(function(){ + throw error; + }); + } else { + throw error; + } + + }, + + /** + * Runs a single test based on the data provided in the node. + * @param {TestNode} node The TestNode representing the test to run. + * @return {Void} + * @static + * @private + * @name _runTest + */ + _runTest : function (node) { + + //get relevant information + var testName = node.testObject, + testCase = node.parent.testObject, + test = testCase[testName], + + //get the "should" test cases + shouldIgnore = testName.indexOf("ignore:") === 0 || + !inGroups(testCase.groups, this._groups) || + (testCase._should.ignore || {})[testName]; //deprecated + + //figure out if the test should be ignored or not + if (shouldIgnore){ + + //update results + node.parent.results[testName] = { + result: "ignore", + message: "Test ignored", + type: "test", + name: testName.indexOf("ignore:") === 0 ? testName.substring(7) : testName + }; + + node.parent.results.ignored++; + node.parent.results.total++; + + this.fire({ type: this.TEST_IGNORE_EVENT, testCase: testCase, testName: testName }); + + //some environments don't support setTimeout + if (typeof setTimeout != "undefined"){ + setTimeout(function(){ + YUITest.TestRunner._run(); + }, 0); + } else { + this._run(); + } + + } else { + + //mark the start time + node._start = new Date(); + + //run the setup + this._execNonTestMethod(node.parent, "setUp", false); + + //now call the body of the test + this._resumeTest(test); + } + + }, + + //------------------------------------------------------------------------- + // Misc Methods + //------------------------------------------------------------------------- + + /** + * Retrieves the name of the current result set. + * @return {String} The name of the result set. + * @method getName + */ + getName: function(){ + return this.masterSuite.name; + }, + + /** + * The name assigned to the master suite of the TestRunner. This is the name + * that is output as the root's name when results are retrieved. + * @param {String} name The name of the result set. + * @return {Void} + * @method setName + */ + setName: function(name){ + this.masterSuite.name = name; + }, + + //------------------------------------------------------------------------- + // Public Methods + //------------------------------------------------------------------------- + + /** + * Adds a test suite or test case to the list of test objects to run. + * @param testObject Either a TestCase or a TestSuite that should be run. + * @return {Void} + * @method add + * @static + */ + add : function (testObject) { + this.masterSuite.add(testObject); + return this; + }, + + /** + * Removes all test objects from the runner. + * @return {Void} + * @method clear + * @static + */ + clear : function () { + this.masterSuite = new YUITest.TestSuite("yuitests" + (new Date()).getTime()); + }, + + /** + * Indicates if the TestRunner is waiting for a test to resume + * @return {Boolean} True if the TestRunner is waiting, false if not. + * @method isWaiting + * @static + */ + isWaiting: function() { + return this._waiting; + }, + + /** + * Indicates that the TestRunner is busy running tests and therefore can't + * be stopped and results cannot be gathered. + * @return {Boolean} True if the TestRunner is running, false if not. + * @method isRunning + */ + isRunning: function(){ + return this._running; + }, + + /** + * Returns the last complete results set from the TestRunner. Null is returned + * if the TestRunner is running or no tests have been run. + * @param {Function} format (Optional) A test format to return the results in. + * @return {Object|String} Either the results object or, if a test format is + * passed as the argument, a string representing the results in a specific + * format. + * @method getResults + */ + getResults: function(format){ + if (!this._running && this._lastResults){ + if (typeof format == "function"){ + return format(this._lastResults); + } else { + return this._lastResults; + } + } else { + return null; + } + }, + + /** + * Returns the coverage report for the files that have been executed. + * This returns only coverage information for files that have been + * instrumented using YUI Test Coverage and only those that were run + * in the same pass. + * @param {Function} format (Optional) A coverage format to return results in. + * @return {Object|String} Either the coverage object or, if a coverage + * format is specified, a string representing the results in that format. + * @method getCoverage + */ + getCoverage: function(format){ + if (!this._running && typeof _yuitest_coverage == "object"){ + if (typeof format == "function"){ + return format(_yuitest_coverage); + } else { + return _yuitest_coverage; + } + } else { + return null; + } + }, + + /** + * Used to continue processing when a method marked with + * "async:" is executed. This should not be used in test + * methods, only in init(). Each argument is a string, and + * when the returned function is executed, the arguments + * are assigned to the context data object using the string + * as the key name (value is the argument itself). + * @private + * @return {Function} A callback function. + */ + callback: function(){ + var names = arguments, + data = this._context, + that = this; + + return function(){ + for (var i=0; i < arguments.length; i++){ + data[names[i]] = arguments[i]; + } + that._run(); + }; + }, + + /** + * Resumes the TestRunner after wait() was called. + * @param {Function} segment The function to run as the rest + * of the haulted test. + * @return {Void} + * @method resume + * @static + */ + resume : function (segment) { + if (this._waiting){ + this._resumeTest(segment || function(){}); + } else { + throw new Error("resume() called without wait()."); + } + }, + + /** + * Runs the test suite. + * @param {Object|Boolean} options (Optional) Options for the runner: + * oldMode indicates the TestRunner should work in the YUI <= 2.8 way + * of internally managing test suites. groups is an array + * of test groups indicating which tests to run. + * @return {Void} + * @method run + * @static + */ + run : function (options) { + + options = options || {}; + + //pointer to runner to avoid scope issues + var runner = YUITest.TestRunner, + oldMode = options.oldMode; + + + //if there's only one suite on the masterSuite, move it up + if (!oldMode && this.masterSuite.items.length == 1 && this.masterSuite.items[0] instanceof YUITest.TestSuite){ + this.masterSuite = this.masterSuite.items[0]; + } + + //determine if there are any groups to filter on + runner._groups = (options.groups instanceof Array) ? "," + options.groups.join(",") + "," : ""; + + //initialize the runner + runner._buildTestTree(); + runner._context = {}; + runner._root._start = new Date(); + + //fire the begin event + runner.fire(runner.BEGIN_EVENT); + + //begin the testing + runner._run(); + } + }); + + return new TestRunner(); + + }(); + +/*! + * Portions of this code incorporated from CSS Lint: + * https://github.com/stubbornella/csslint + */ + +importPackage(java.io); +importPackage(java.lang); + +YUITest.CLI = { + args: arguments, + + print: function(message){ + System.out.print(message); + }, + + println: print, + + warn: function(message){ + System.err.print(message); + }, + + quit: quit, + + isDirectory: function(name){ + var dir = new File(name); + return dir.isDirectory(); + }, + + getFiles: function(dir){ + var files = []; + + function traverse(dir) { + var dirList = dir.listFiles(); + dirList.forEach(function (file) { + if (/\.js$/.test(file)) { + files.push(file.toString()); + } else if (file.isDirectory()) { + traverse(file); + } + }); + } + + traverse(new File(dir)); + + return files; + }, + + getFullPath: function(filename){ + return (new File(filename)).getCanonicalPath(); + }, + + readFile: readFile, + + processFiles: function(){ + var files = this.files, + i, len, output; + + if (files.length){ + for (i=0, len=files.length; i < len; i++){ + + if (this.options.verbose){ + this.warn("[INFO] Loading " + files[i] + "\n"); + } + + load(files[i]); + + } + } else { + this.warn("[ERROR] No tests to run, exiting.\n"); + this.quit(1); + } + } +}; + + + + + +/** + * Console output that mimics logger output from YUI Test for YUI 2/3. + * @namespace YUITest.Node.CLI + * @class Logger + * @constructor + */ +YUITest.CLI.Logger = function(){ + + var testRunner = YUITest.TestRunner, + cli = YUITest.CLI; + + //handles test runner events + function handleEvent(event){ + + var message = ""; + switch(event.type){ + case testRunner.BEGIN_EVENT: + message = "Testing began at " + (new Date()).toString() + "."; + messageType = "info"; + break; + + case testRunner.COMPLETE_EVENT: + message = "Testing completed at " + + (new Date()).toString() + ".\n" + + "Passed:" + event.results.passed + " Failed:" + event.results.failed + + " Total:" + event.results.total + "(" + event.results.ignored + " ignored)"; + messageType = "info"; + break; + + case testRunner.TEST_FAIL_EVENT: + message = event.testName + ": failed.\n" + event.error.getMessage(); + messageType = "fail"; + break; + + case testRunner.ERROR_EVENT: + message = event.methodName + ": error.\n" + event.error.message; + messageType = "error"; + break; + + case testRunner.TEST_IGNORE_EVENT: + message = event.testName + ": ignored."; + messageType = "ignore"; + break; + + case testRunner.TEST_PASS_EVENT: + message = event.testName + ": passed."; + messageType = "pass"; + break; + + case testRunner.TEST_SUITE_BEGIN_EVENT: + message = "Test suite \"" + event.testSuite.name + "\" started."; + messageType = "info"; + break; + + case testRunner.TEST_SUITE_COMPLETE_EVENT: + message = "Testing completed at " + + (new Date()).toString() + ".\n" + + "Passed:" + event.results.passed + " Failed:" + event.results.failed + + " Total:" + event.results.total + "(" + event.results.ignored + " ignored)"; + messageType = "info"; + break; + + case testRunner.TEST_CASE_BEGIN_EVENT: + message = "Test case \"" + event.testCase.name + "\" started."; + messageType = "info"; + break; + + case testRunner.TEST_CASE_COMPLETE_EVENT: + message = "Testing completed at " + + (new Date()).toString() + ".\n" + + "Passed:" + event.results.passed + " Failed:" + event.results.failed + + " Total:" + event.results.total + "(" + event.results.ignored + " ignored)"; + messageType = "info"; + break; + default: + message = "Unexpected event " + event.type; + messageType = "info"; + } + + cli.print(message + "\n"); + } + + testRunner.subscribe(testRunner.BEGIN_EVENT, handleEvent) + testRunner.subscribe(testRunner.TEST_FAIL_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_PASS_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_IGNORE_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_CASE_BEGIN_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_CASE_COMPLETE_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_SUITE_BEGIN_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, handleEvent); + testRunner.subscribe(testRunner.COMPLETE_EVENT, handleEvent); + +}; + + + +/** + * Console output that mimics XUnit output. + * @namespace YUITest.CLI + * @class XUnit + * @constructor + */ +YUITest.CLI.XUnit = function(){ + + var testRunner = YUITest.TestRunner, + cli = YUITest.CLI, + errors = [], + failures = [], + stack = []; + + function filterStackTrace(stackTrace){ + if (stackTrace){ + var lines = stackTrace.split("\n"), + result = [], + i, len; + + //skip first line, it's the error + for (i=1, len=lines.length; i < len; i++){ + if (lines[i].indexOf("yuitest-node") > -1){ + break; + } else { + result.push(lines[i]); + } + } + + return result.join("\n"); + } else { + return "Unavailable." + } + } + + //handles test runner events + function handleEvent(event){ + + var message = "", + results = event.results, + i, len; + + switch(event.type){ + case testRunner.BEGIN_EVENT: + message = "YUITest for Node.js\n"; + + if (testRunner._groups){ + message += "Filtering on groups '" + testRunner._groups.slice(1,-1) + "'\n"; + } + break; + + case testRunner.COMPLETE_EVENT: + message = "\nTotal tests: " + results.total + ", Failures: " + + results.failed + ", Skipped: " + results.ignored + + ", Time: " + (results.duration/1000) + " seconds\n"; + + if (failures.length){ + message += "\nTests failed:\n"; + + for (i=0,len=failures.length; i < len; i++){ + message += "\n" + (i+1) + ") " + failures[i].name + " : " + failures[i].error.getMessage() + "\n"; + message += "Stack trace:\n" + filterStackTrace(failures[i].error.stack) + "\n"; + } + + message += "\n"; + } + + if (errors.length){ + message += "\nErrors:\n"; + + for (i=0,len=errors.length; i < len; i++){ + message += "\n" + (i+1) + ") " + errors[i].name + " : " + errors[i].error.message + "\n"; + message += "Stack trace:\n" + filterStackTrace(errors[i].error.stack) + "\n"; + } + + message += "\n"; + } + + message += "\n\n"; + break; + + case testRunner.TEST_FAIL_EVENT: + message = "F"; + failures.push({ + name: stack.concat([event.testName]).join(" > "), + error: event.error + }); + + break; + + case testRunner.ERROR_EVENT: + errors.push({ + name: stack.concat([event.methodName]).join(" > "), + error: event.error + }); + + break; + + case testRunner.TEST_IGNORE_EVENT: + message = "S"; + break; + + case testRunner.TEST_PASS_EVENT: + message = "."; + break; + + case testRunner.TEST_SUITE_BEGIN_EVENT: + stack.push(event.testSuite.name); + break; + + case testRunner.TEST_CASE_COMPLETE_EVENT: + case testRunner.TEST_SUITE_COMPLETE_EVENT: + stack.pop(); + break; + + case testRunner.TEST_CASE_BEGIN_EVENT: + stack.push(event.testCase.name); + break; + + //no default + } + + cli.print(message); + } + + testRunner.subscribe(testRunner.BEGIN_EVENT, handleEvent) + testRunner.subscribe(testRunner.TEST_FAIL_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_PASS_EVENT, handleEvent); + testRunner.subscribe(testRunner.ERROR_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_IGNORE_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_CASE_BEGIN_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_CASE_COMPLETE_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_SUITE_BEGIN_EVENT, handleEvent); + testRunner.subscribe(testRunner.TEST_SUITE_COMPLETE_EVENT, handleEvent); + testRunner.subscribe(testRunner.COMPLETE_EVENT, handleEvent); + +}; + + + +/** + * Console output that uses TestFormat formats. + * @namespace YUITest.Node.CLI + * @class Format + * @constructor + */ +YUITest.CLI.Format = function(format){ + + var testRunner = YUITest.TestRunner, + cli = YUITest.CLI; + + //handles test runner events + function handleEvent(event){ + + var results = event.results; + + cli.print(format(results)); + } + + testRunner.subscribe(testRunner.COMPLETE_EVENT, handleEvent); + +}; + +/* + * Augments the environment-specific CLI API with common functionality. + */ +YUITest.Util.mix(YUITest.CLI, { + + files: [], + + options: { + verbose: false, + webcompat: false, + help: false, + format: "xunit" + }, + + outputHelp: function(){ + this.print([ + "\nUsage: yuitest [options] [file|dir]*", + " ", + "Global Options", + " --groups groupname Run only tests cases that are part of groupname.", + " --help Displays this information.", + " --format Specifies output format (junitxml, tap, xunit).", + " --verbose Display informational messages and warnings.", + " --webcompat Load tests designed for use in browsers." + ].join("\n") + "\n\n"); + }, + + processArguments: function(){ + + var args = this.args, + arg = args.shift(), + files = []; + + while(arg){ + if (arg.indexOf("--") == 0){ + this.options[arg.substring(2)] = true; + + //get the next argument + if (arg == "--groups" || arg == "--format"){ + this.options[arg.substring(2)] = args.shift(); + } + } else { + + //see if it's a directory or a file + if (this.isDirectory(arg)){ + files = files.concat(this.getFiles(arg)); + } else { + files.push(arg); + } + } + arg = args.shift(); + } + + if (this.options.help || files.length === 0){ + this.outputHelp(); + this.quit(0); + } + + this.files = files; + + //----------------------------------------------------------------------------- + // Determine output format + //----------------------------------------------------------------------------- + + switch(this.options.format){ + case "junitxml": + if (this.options.verbose){ + this.warn("[INFO] Using JUnitXML output format.\n"); + } + YUITest.CLI.Format(YUITest.TestFormat.JUnitXML); + break; + case "tap": + if (this.options.verbose){ + this.warn("[INFO] Using TAP output format.\n"); + } + YUITest.CLI.Format(YUITest.TestFormat.TAP); + break; + default: + if (this.options.verbose){ + this.warn("[INFO] Using XUnit output format.\n"); + } + YUITest.CLI.XUnit(); + } + }, + + start: function(){ + + this.processArguments(); + this.processFiles(); + + YUITest.TestRunner.run({ + groups: this.options.groups ? this.options.groups.split(",") : null + }); + } +}); + +YUITest.CLI.start(); + diff --git a/src/css/Combinator.js b/src/css/Combinator.js index 471c595e..0a165543 100644 --- a/src/css/Combinator.js +++ b/src/css/Combinator.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css diff --git a/src/css/MediaFeature.js b/src/css/MediaFeature.js index 0efd1a7c..0fb96cdd 100644 --- a/src/css/MediaFeature.js +++ b/src/css/MediaFeature.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a media feature, such as max-width:500. * @namespace parserlib.css diff --git a/src/css/MediaQuery.js b/src/css/MediaQuery.js index 3ced7360..3a1a048b 100644 --- a/src/css/MediaQuery.js +++ b/src/css/MediaQuery.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents an individual media query. * @namespace parserlib.css diff --git a/src/css/Parser.js b/src/css/Parser.js index 8aedd91d..71d87656 100644 --- a/src/css/Parser.js +++ b/src/css/Parser.js @@ -1,3 +1,7 @@ +/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, + PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, + PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ + /** * A CSS3 parser. * @namespace parserlib.css @@ -145,7 +149,7 @@ Parser.prototype = function(){ } else { //not a syntax error, rethrow it - throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);; + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); } break; case Tokens.S: @@ -2008,10 +2012,9 @@ Parser.prototype = function(){ tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ //if there's a semicolon, then there might be another declaration - this._readDeclarations(false, readMargins); - } else if (tt == Tokens.RBRACE){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ //if there's a right brace, the rule is finished so don't do anything - } else { //otherwise, rethrow the error because it wasn't handled properly throw ex; } @@ -2192,7 +2195,9 @@ Parser.prototype = function(){ //copy over onto prototype for (prop in additions){ - proto[prop] = additions[prop]; + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } } return proto; diff --git a/src/css/Properties.js b/src/css/Properties.js index be0e2571..06c787f0 100644 --- a/src/css/Properties.js +++ b/src/css/Properties.js @@ -1,4 +1,5 @@ //This file will likely change a lot! Very experimental! +/*global ValidationError*/ var ValidationType = { diff --git a/src/css/PropertyName.js b/src/css/PropertyName.js index e9bd351d..de5660bf 100644 --- a/src/css/PropertyName.js +++ b/src/css/PropertyName.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). * @namespace parserlib.css diff --git a/src/css/PropertyValue.js b/src/css/PropertyValue.js index c9f1d536..158d2b40 100644 --- a/src/css/PropertyValue.js +++ b/src/css/PropertyValue.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a CSS property value, meaning that it represents * just everything single part between ":" and ";". If there are multiple values diff --git a/src/css/PropertyValuePart.js b/src/css/PropertyValuePart.js index f6a4ee84..132d6b26 100644 --- a/src/css/PropertyValuePart.js +++ b/src/css/PropertyValuePart.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser, Colors*/ /** * Represents a single part of a CSS property value, meaning that it represents * just one part of the data between ":" and ";". @@ -151,7 +152,7 @@ function PropertyValuePart(text, line, col){ } PropertyValuePart.prototype = new SyntaxUnit(); -PropertyValuePart.prototype.constructor = PropertyValue; +PropertyValuePart.prototype.constructor = PropertyValuePart; /** * Create a new syntax unit based solely on the given token. diff --git a/src/css/Selector.js b/src/css/Selector.js index 331d09cd..6bc7e51a 100644 --- a/src/css/Selector.js +++ b/src/css/Selector.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser, Specificity*/ /** * Represents an entire single selector, including all parts but not * including multiple selectors (those separated by commas). diff --git a/src/css/SelectorPart.js b/src/css/SelectorPart.js index 409413fd..234b0ad8 100644 --- a/src/css/SelectorPart.js +++ b/src/css/SelectorPart.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a single part of a selector string, meaning a single set of * element name and modifiers. This does not include combinators such as diff --git a/src/css/SelectorSubPart.js b/src/css/SelectorSubPart.js index 68972297..73b5f362 100644 --- a/src/css/SelectorSubPart.js +++ b/src/css/SelectorSubPart.js @@ -1,3 +1,4 @@ +/*global SyntaxUnit, Parser*/ /** * Represents a selector modifier string, meaning a class name, element name, * element ID, pseudo rule, etc. diff --git a/src/css/Specificity.js b/src/css/Specificity.js index 0dbca2bd..d13ca268 100644 --- a/src/css/Specificity.js +++ b/src/css/Specificity.js @@ -1,3 +1,4 @@ +/*global Pseudos, SelectorPart*/ /** * Represents a selector's specificity. * @namespace parserlib.css @@ -69,6 +70,7 @@ Specificity.prototype = { Specificity.calculate = function(selector){ var i, len, + part, b=0, c=0, d=0; function updateValues(part){ diff --git a/src/css/TokenStream.js b/src/css/TokenStream.js index e233c439..c985c785 100755 --- a/src/css/TokenStream.js +++ b/src/css/TokenStream.js @@ -1,4 +1,4 @@ - +/*global Tokens, TokenStreamBase*/ var h = /^[0-9a-fA-F]$/, nonascii = /^[\u0080-\uFFFF]$/, @@ -10,31 +10,31 @@ var h = /^[0-9a-fA-F]$/, function isHexDigit(c){ - return c != null && h.test(c); + return c !== null && h.test(c); } function isDigit(c){ - return c != null && /\d/.test(c); + return c !== null && /\d/.test(c); } function isWhitespace(c){ - return c != null && /\s/.test(c); + return c !== null && /\s/.test(c); } function isNewLine(c){ - return c != null && nl.test(c); + return c !== null && nl.test(c); } function isNameStart(c){ - return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); + return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); } function isNameChar(c){ - return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c)); + return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c)); } function isIdentStart(c){ - return c != null && (isNameStart(c) || /\-\\/.test(c)); + return c !== null && (isNameStart(c) || /\-\\/.test(c)); } function mix(receiver, supplier){ @@ -225,8 +225,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { token = this.unicodeRangeToken(c, startLine, startCol); break; } - /*falls through*/ - + /* falls through */ default: /* @@ -279,11 +278,9 @@ TokenStream.prototype = mix(new TokenStreamBase(), { //make sure this token is wanted //TODO: check channel break; - - c = reader.read(); } - if (!token && c == null){ + if (!token && c === null){ token = this.createToken(Tokens.EOF,null,startLine,startCol); } @@ -567,7 +564,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { break; } else { temp = this.readComment(c); - if (temp == ""){ //broken! + if (temp === ""){ //broken! break; } } @@ -708,7 +705,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ tt = Tokens.INVALID; } @@ -873,7 +870,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if c is null, that means we're out of input and the string was never closed - if (c == null){ + if (c === null){ string = ""; } @@ -909,7 +906,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), { } //if there was no inner value or the next character isn't closing paren, it's not a URI - if (inner == "" || c != ")"){ + if (inner === "" || c != ")"){ uri = first; reader.reset(); } else { diff --git a/src/util/TokenStreamBase.js b/src/util/TokenStreamBase.js index c7af438a..d88da5b1 100644 --- a/src/util/TokenStreamBase.js +++ b/src/util/TokenStreamBase.js @@ -1,3 +1,5 @@ +/*global StringReader, SyntaxError*/ + /** * Generic TokenStream providing base functionality. * @class TokenStreamBase @@ -14,7 +16,6 @@ function TokenStreamBase(input, tokenData){ * @property _reader * @private */ - //this._reader = (typeof input == "string") ? new StringReader(input) : input; this._reader = input ? new StringReader(input.toString()) : null; /** @@ -180,7 +181,7 @@ TokenStreamBase.prototype = { */ advance: function(tokenTypes, channel){ - while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){ + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } From 21c91f8b817ba4f90aa6592f8969af5c41cb0d22 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 17 Nov 2011 10:37:03 -0800 Subject: [PATCH 025/313] Ported tests to command line and new version of YUI Test --- build.xml | 11 +- build/node-parserlib.js | 4 +- build/parserlib-core.js | 2 +- build/parserlib-css.js | 2 +- build/parserlib-tests.js | 2337 ++++++++++++++++++++++++++++++++++++++ build/parserlib.js | 4 +- tests/css/Parser.js | 1716 ++++++++++++++++++++++++++++ tests/css/Specificity.js | 142 +++ tests/css/TokenStream.js | 479 ++++++++ 9 files changed, 4686 insertions(+), 11 deletions(-) create mode 100644 build/parserlib-tests.js create mode 100644 tests/css/Parser.js create mode 100644 tests/css/Specificity.js create mode 100644 tests/css/TokenStream.js diff --git a/build.xml b/build.xml index 1b7eb59b..c142b8b9 100644 --- a/build.xml +++ b/build.xml @@ -79,13 +79,14 @@ - + + - - + + @@ -211,7 +212,7 @@ - + @@ -228,6 +229,6 @@ - + diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 21150dd4..5a4c0f3d 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 58f9527f..729830c4 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index bfbd8e45..8fce3c9d 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib-tests.js b/build/parserlib-tests.js new file mode 100644 index 00000000..7fccf557 --- /dev/null +++ b/build/parserlib-tests.js @@ -0,0 +1,2337 @@ +(function(){ + + var Assert = YUITest.Assert, + MediaQuery = parserlib.css.MediaQuery, + Selector = parserlib.css.Selector, + Combinator = parserlib.css.Combinator, + SelectorPart = parserlib.css.SelectorPart, + Parser = parserlib.css.Parser; + + //------------------------------------------------------------------------- + // Base Test Suite + //------------------------------------------------------------------------- + + var suite = new YUITest.TestSuite("Selector Parsing"); + + suite.add(new YUITest.TestCase({ + + name: "Type Selector Tests", + + testSimpleTypeSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(Parser.SELECTOR_TYPE, result.type); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual(Parser.SELECTOR_PART_TYPE, result.parts[0].type); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("svg|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(Parser.SELECTOR_TYPE, result.type); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("svg|rect", result.parts[0].elementName, "Element name should be 'svg|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusBlankNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("|rect", result.parts[0].elementName, "Element name should be '|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*|rect", result.parts[0].elementName, "Element name should be '*|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Universal Selector Tests", + + testSimpleUniversalSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*", result.parts[0].elementName, "Element name should be '*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("svg|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("svg|*", result.parts[0].elementName, "Element name should be 'svg|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusBlankNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("|*", result.parts[0].elementName, "Element name should be '|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*|*", result.parts[0].elementName, "Element name should be '*|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "Attribute Selector Tests", + + testAttributePresenceSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class]", result.parts[0].modifiers[0].text, "Modifier text should be '[class]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEquivalenceSelectorNoString: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeContainsSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class~=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class~=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class~=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeDashMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class|=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class|=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class|=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeStartMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("object[type^=\"image/\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("object", result.parts[0].elementName, "Element name should be 'object'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[type^=\"image/\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[type^=\"image/\"]'."); + Assert.areEqual(7, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEndMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a[href$=\".html\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName, "Element name should be 'a'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[href$=\".html\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[href$=\".html\"]'."); + Assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeContainsMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("p[title*=\"hello\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("p", result.parts[0].elementName, "Element name should be 'p'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[title*=\"hello\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[title*=\"hello\"]'."); + Assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEquivalenceSelectorNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[html|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[html|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[html|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelectorUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[*|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[*|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[*|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelectorDefaultNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + } + })); + + + suite.add(new YUITest.TestCase({ + + name: "Class Selector Tests", + + testSimpleClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector(".selected"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual(1, result.parts[0].line, "Line start should be 1"); + Assert.areEqual(1, result.parts[0].col, "Column start should be 1"); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + + }, + + testCompoundClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector(".selected.foo"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have two modifiers."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual("class", result.parts[0].modifiers[1].type, "Modifier type should be 'class'."); + Assert.areEqual(".foo", result.parts[0].modifiers[1].text, "Modifier text should be '.foo'."); + }, + + testSimpleClassSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.selected"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li",result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line start should be 1"); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Column start should be 3"); + + }, + + testCompoundClassSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.selected.foo"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have two modifiers."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line start should be 1"); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Column start should be 3"); + Assert.areEqual("class", result.parts[0].modifiers[1].type, "Modifier type should be 'class'."); + Assert.areEqual(".foo", result.parts[0].modifiers[1].text, "Modifier text should be '.foo'."); + Assert.areEqual(1, result.parts[0].modifiers[1].line, "Line start should be 1"); + Assert.areEqual(12, result.parts[0].modifiers[1].col, "Column start should be 12"); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "ID Selector Tests", + + testSimpleIDSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("#header"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("id", result.parts[0].modifiers[0].type, "Modifier type should be 'id'."); + Assert.areEqual("#header", result.parts[0].modifiers[0].text, "Modifier text should be '#header'."); + }, + + testSimpleIDSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("div#header"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("div", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("id", result.parts[0].modifiers[0].type, "Modifier type should be 'id'."); + Assert.areEqual("#header", result.parts[0].modifiers[0].text, "Modifier text should be '#header'."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Pseudo Class Selector Tests", + + testSimplePseudoClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a:hover"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":hover", result.parts[0].modifiers[0].text, "Modifier text should be ':hover'."); + }, + + testMultiplePseudoClassSelectors: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a:focus:hover"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":focus", result.parts[0].modifiers[0].text, "Modifier text should be ':focus'."); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text, "Modifier text should be ':hover'."); + }, + + testPseudoClassFunctionSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("html:lang(fr-be)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("html", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":lang(fr-be)", result.parts[0].modifiers[0].text, "Modifier text should be ':lang(fr-be)'."); + }, + + testPseudoClassNthSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(2n+1)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(2n+1)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(2n+1)'."); + }, + + testPseudoClassNthSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(even)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(even)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(even)'."); + }, + + testPseudoClassNthSelector3: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(5)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(5)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(5)'."); + }, + + testPseudoClassNthSelector4: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-of-type(5)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-of-type(5)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-of-type(5)'."); + }, + + testPseudoClassLastChildSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:last-child"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":last-child", result.parts[0].modifiers[0].text, "Modifier text should be ':last-child'."); + }, + + testPseudoClassNotSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("button:not([DISABLED])"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("button", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("not", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":not([DISABLED])", result.parts[0].modifiers[0].text, "Modifier text should be ':not([DISABLED])'."); + Assert.areEqual(1, result.parts[0].modifiers[0].args.length, "Modifier should have one argument."); + + var arg = result.parts[0].modifiers[0].args[0]; + + Assert.isInstanceOf(SelectorPart, arg, "Result should be an instance of Selector."); + Assert.areEqual("[DISABLED]", arg.toString()); + Assert.isNull(arg.elementName); + Assert.areEqual(1, arg.modifiers.length); + Assert.areEqual("attribute", arg.modifiers[0].type); + }, + + testPseudoClassNotSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("button:not(foo)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("button", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("not", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":not(foo)", result.parts[0].modifiers[0].text, "Modifier text should be ':not(foo)'."); + Assert.areEqual(1, result.parts[0].modifiers[0].args.length, "Modifier should have one argument."); + + + var arg = result.parts[0].modifiers[0].args[0]; + + Assert.isInstanceOf(SelectorPart, arg, "Result should be an instance of Selector."); + Assert.areEqual("foo", arg.toString()); + Assert.areEqual("foo", arg.elementName, "Element name should be 'foo'."); + Assert.areEqual(0, arg.modifiers.length); + + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Pseudo Element Selector Tests", + + testSimplePseudoElementSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("p::first-line"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("p", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual("::first-line", result.parts[0].modifiers[0].text, "Modifier text should be '::first-line'."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Combinators", + + + testChildCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover > p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorNoSpaces: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover>p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorOneSpaceBefore: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover >p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorOneSpaceAfter: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover> p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testAdjacentSiblingCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover + p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("+", result.parts[1].text); + Assert.areEqual("adjacent-sibling", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testGeneralSiblingCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover ~ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("~", result.parts[1].text); + Assert.areEqual("sibling", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testDescendantCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "The line should be 1."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "The column should be 3."); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.areEqual(1, result.parts[0].modifiers[1].line, "The line should be 1."); + Assert.areEqual(10, result.parts[0].modifiers[1].col, "The column should be 10."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(" ", result.parts[1].text); + Assert.areEqual("descendant", result.parts[1].type); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(16, result.parts[1].col, "Column should be 16."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + Assert.areEqual(1, result.parts[2].elementName.line, "Line should be 1."); + Assert.areEqual(17, result.parts[2].elementName.col, "Column should be 17."); + }, + + testDescendantCombinatorWithTrailingWhitespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover p "); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(" ", result.parts[1].text); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testWithCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover > p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(17, result.parts[1].col, "Column should be 17."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithNthChild: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(2n+1) a"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + } + + + //body > h2:nth-of-type(n+2):nth-last-of-type(n+2) + //body > h2:not(:first-of-type):not(:last-of-type) + //html|*:not(:link):not(:visited) + })); + + suite.add(new YUITest.TestCase({ + + name: "Complex Cases", + + testWithComplexSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("body > h2:nth-of-type(n+2):nth-last-of-type(n+2)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(6, result.parts[1].col, "Column should be 6."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual(1, result.parts[2].line, "Line should be 1."); + Assert.areEqual(8, result.parts[2].col, "Column should be 8."); + }, + + testWithComplexSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("body > h2:not(:first-of-type):not(:last-of-type)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithComplexSelector3: function(){ + var parser = new Parser(); + var result = parser.parseSelector("html|*:not(:link):not(:visited)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Should be one part."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + //Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + //Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithMultipartSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("ul li a span"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(7, result.parts.length, "Should be four parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "Part should be a SelectorPart."); + Assert.areEqual("ul", result.parts[0].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[2], "Part should be a SelectorPart."); + Assert.areEqual("li", result.parts[2].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[4], "Part should be a SelectorPart."); + Assert.areEqual("a", result.parts[4].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[6], "Part should be a SelectorPart."); + Assert.areEqual("span", result.parts[6].elementName); + + } + + + + })); + + + suite.add(new YUITest.TestCase({ + + name: "Media Queries", + + + testSimpleMediaQuery: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.isNull(result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testSimpleMediaQueryNot: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("not print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("not", result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testSimpleMediaQueryOnly: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("only print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("only", result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testComplexMediaQuery: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("screen and (max-weight: 3kg) and (color)"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.isNull(result.modifier); + Assert.areEqual("screen", result.mediaType); + Assert.areEqual(2, result.features.length, "Should be two features."); + Assert.areEqual("max-weight", result.features[0].name); + Assert.areEqual(25, result.features[0].value.col); + Assert.areEqual("3kg", result.features[0].value); + Assert.areEqual("color", result.features[1].name); + Assert.isNull(result.features[1].value); + Assert.areEqual(35, result.features[1].name.col); + + }, + + testComplexMediaQuery2: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("only screen and (max-device-width: 768px) and (orientation:portrait)"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("only", result.modifier); + Assert.areEqual("screen", result.mediaType); + Assert.areEqual(2, result.features.length, "Should be two features."); + Assert.areEqual("max-device-width", result.features[0].name); + Assert.areEqual("768px", result.features[0].value); + Assert.areEqual("orientation", result.features[1].name); + Assert.areEqual("portrait", result.features[1].value); + } + + + })); + + + suite.add(new YUITest.TestCase({ + + name: "Property Values", + + testDimensionValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("1px"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(1, result.parts[0].value); + Assert.areEqual("px", result.parts[0].units); + }, + + testPercentageValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25.4%"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("percentage", result.parts[0].type); + Assert.areEqual(25.4, result.parts[0].value); + }, + + testIntegerValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("integer", result.parts[0].type); + Assert.areEqual(25, result.parts[0].value); + }, + + testNumberValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25.0"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("number", result.parts[0].type); + Assert.areEqual(25, result.parts[0].value); + }, + + testHexColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("#ffeedd"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + }, + + testRGBColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgb(255, 238 , 221)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + }, + + testRGBColorValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgb(100%,50%, 75%)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(127.5, result.parts[0].green); + Assert.areEqual(191.25, result.parts[0].blue); + }, + + testRGBAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(255, 238 , 221, 0.3)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + Assert.areEqual(0.3, result.parts[0].alpha); + }, + + testRGBAColorValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(100%,50%, 75%, 0.5)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(127.5, result.parts[0].green); + Assert.areEqual(191.25, result.parts[0].blue); + Assert.areEqual(0.5, result.parts[0].alpha); + }, + + testHSLColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsl(100,50%, 75%)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(100, result.parts[0].hue); + Assert.areEqual(0.5, result.parts[0].saturation); + Assert.areEqual(0.75, result.parts[0].lightness); + }, + + testHSLAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsla(100,50%, 75%, 0.5)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(100, result.parts[0].hue); + Assert.areEqual(0.5, result.parts[0].saturation); + Assert.areEqual(0.75, result.parts[0].lightness); + Assert.areEqual(0.5, result.parts[0].alpha); + }, + + testColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("red"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(0, result.parts[0].green); + Assert.areEqual(0, result.parts[0].blue); + }, + + testURIValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url(http://www.yahoo.com/)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testURIValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url('http://www.yahoo.com/')"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testURIValue3: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url(https://github.com/%22http://www.yahoo.com/")"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testStringValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("'Hello world!'"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("string", result.parts[0].type); + Assert.areEqual("Hello world!", result.parts[0].value); + }, + + testStringValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("\"Hello world!\""); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("string", result.parts[0].type); + Assert.areEqual("Hello world!", result.parts[0].value); + }, + + testValueWithOperators: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("10px / 1em"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(3, result.parts.length); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[0]); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(10, result.parts[0].value); + Assert.areEqual("px", result.parts[0].units); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[1]); + Assert.areEqual("operator", result.parts[1].type); + Assert.areEqual("/", result.parts[1].text); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(6, result.parts[1].col, "Column should be 6."); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[2]); + Assert.areEqual("length", result.parts[2].type); + Assert.areEqual(1, result.parts[2].value); + Assert.areEqual("em", result.parts[2].units); + }, + + testValueWithOperators2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("1em/1.5em \"Times New Roman\", Times, serif"); + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(8, result.parts.length); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[0]); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(1, result.parts[0].value); + Assert.areEqual("em", result.parts[0].units); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[1]); + Assert.areEqual("operator", result.parts[1].type); + Assert.areEqual("/", result.parts[1].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[2]); + Assert.areEqual("length", result.parts[2].type); + Assert.areEqual(1.5, result.parts[2].value); + Assert.areEqual("em", result.parts[2].units); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[3]); + Assert.areEqual("string", result.parts[3].type); + Assert.areEqual("Times New Roman", result.parts[3].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[4]); + Assert.areEqual("operator", result.parts[4].type); + Assert.areEqual(",", result.parts[4].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[5]); + Assert.areEqual("identifier", result.parts[5].type); + Assert.areEqual("Times", result.parts[5].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[6]); + Assert.areEqual("operator", result.parts[6].type); + Assert.areEqual(",", result.parts[6].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[7]); + Assert.areEqual("identifier", result.parts[7].type); + Assert.areEqual("serif", result.parts[7].value); + } + + + + })); + + suite.add(new YUITest.TestCase({ + + name: "Rules", + + testRuleWithOnePartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithTwoPartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithThreePartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li a{ color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithFourPartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li a span { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Special Cases", + + _should: { + error: { + testIEFilter5: "Unexpected token '=' at line 1, col 14." + } + }, + + testWithCommentAndSpaces: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li /*booya*/ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testWithCommentAndTrailingSpace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li/*booya*/ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testWithCommentAndLeadingSpace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li /*booya*/p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testIEFilter: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.Wave(strength=100)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + }, + + testIEFilter2: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=http://l.yimg.com/ne/home/metro/pa/map/gugimap_btn_mapview.png, sizingMethod=image)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + + }, + + testIEFilter3: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', src='http://l.yimg.com/ne/home/metro/pa/map/gugimap_btn_mapview.png', sizingMethod='image')"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + + }, + + testIEFilter4: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("alpha(opacity=10)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("alpha(opacity=10)", result.text); + Assert.areEqual("unknown", result.parts[0].type); + }, + + testIEFilter5: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("alpha(opacity=10)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + } + + + + + })); + + suite.add(new YUITest.TestCase({ + + name: "Animation Parsing Tests", + + testWebKitKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@-webkit-keyframes movingbox{0%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testMozKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@-moz-keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFramesFromTo: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes movingbox{from{left:90%;-webkit-transform: rotate(0deg);}to{left:10%;-webkit-transform: rotate(360deg);}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFramesWithWhitespace: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes 'diagonal-slide' { from { left: 0; top: 0; } to { left: 100px; top: 100px; } }"); + Assert.isTrue(true); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "General Parsing Tests", + + testMediaWithPage: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media { @page {} }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithTypeOnly: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media print { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithTypesOnly: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media print, screen { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithSimpleExpression: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media (max-width:400px) { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithComplexExpression: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media all and (max-width:400px) { }"); + Assert.isTrue(true); //just don't want an error + }, + + testClassesWithEscapes: function(){ + var parser = new Parser({strict:true}); + var result = parser.parseSelector("#\\31 a2b3c"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("#\\31 a2b3c", result.parts[0].toString(), "Selector should be correct."); + Assert.areEqual(1, result.parts.length, "Should be one part."); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "Validation Tests", + + testInvalidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected color or one of (inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: foo; }"); + + }, + + testInvalidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected color or one of (inherit) but found 'invert'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: invert; }"); + + }, + + testValidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: red; }"); + + }, + + testValidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: #ff0000; }"); + + }, + + testValidColor3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: inherit; }"); + + }, + + testValidColor4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-color: transparent; }"); + + }, + + testBackgroundAttachment1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: scroll; }"); + + }, + + testBackgroundAttachment2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: fixed; }"); + + }, + + testBackgroundAttachment3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: local; }"); + + }, + + testInvalidBackgroundAttachment: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected attachment but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { background-attachment: foo; }"); + }, + + testInvalidZIndex: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected integer or one of (auto | inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { z-index: foo; }"); + }, + + testZIndex1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: 1 }"); + + }, + + testZIndex2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: auto }"); + }, + + testZIndex3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: inherit }"); + + }, + + testBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px }"); + + }, + + testBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px }"); + + }, + + testBorderWidth3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px}"); + + }, + + testBorderWidth4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected a max of 4 property values but found 5.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected border-width but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: foo}"); + + }, + + testMinHeight1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1px; }"); + + }, + + testMinHeight2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1%; }"); + + }, + + testMinHeight3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: inherit; }"); + + }, + + testInvalidMinHeight: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected length or percentage or one of (inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { min-height: foo}"); + + }, + + testOpacity: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { opacity: 1}"); + + }, + + testBackgroundImage1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: none}"); + }, + + testBackgroundImage2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png)}"); + }, + + testBackgroundImage3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), none}"); + }, + + testBackgroundImage4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), url(https://github.com/bar.png)}"); + }, + + testBackgroundImage5: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected end of line but found ','.", event.invalid.message); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png),}"); + } + + })); + + + YUITest.TestRunner.add(suite); + +})(); +(function(){ + + var Assert = YUITest.Assert, + Parser = parserlib.css.Parser, + Specificity = parserlib.css.Specificity; + + YUITest.TestRunner.add(new YUITest.TestCase({ + + name: "Specificity Tests", + + testSpecificity1: function(){ + var parser = new Parser(), + selector = parser.parseSelector("*"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(0, specificity.valueOf()); + Assert.areEqual("0,0,0,0", specificity.toString()); + }, + + testSpecificity2: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(1, specificity.valueOf()); + Assert.areEqual("0,0,0,1", specificity.toString()); + }, + + testSpecificity3: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li:first-line"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(2, specificity.valueOf()); + Assert.areEqual("0,0,0,2", specificity.toString()); + }, + + testSpecificity4: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(2, specificity.valueOf()); + Assert.areEqual("0,0,0,2", specificity.toString()); + + }, + + testSpecificity5: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul ol+li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(3, specificity.valueOf()); + Assert.areEqual("0,0,0,3", specificity.toString()); + + }, + + testSpecificity6: function(){ + var parser = new Parser(), + selector = parser.parseSelector("h1 + *[rel=up]"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(11, specificity.valueOf()); + Assert.areEqual("0,0,1,1", specificity.toString()); + + }, + + testSpecificity7: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul ol li.red"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(13, specificity.valueOf()); + Assert.areEqual("0,0,1,3", specificity.toString()); + + }, + + testSpecificity8: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li.red.level"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(21, specificity.valueOf()); + Assert.areEqual("0,0,2,1", specificity.toString()); + + }, + + testSpecificity9: function(){ + var parser = new Parser(), + selector = parser.parseSelector(".f00"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(10, specificity.valueOf()); + Assert.areEqual("0,0,1,0", specificity.toString()); + + }, + + testSpecificity10: function(){ + var parser = new Parser(), + selector = parser.parseSelector("div p.foo"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(12, specificity.valueOf()); + Assert.areEqual("0,0,1,2", specificity.toString()); + + }, + + testSpecificity11: function(){ + var parser = new Parser(), + selector = parser.parseSelector("#foo"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(100, specificity.valueOf()); + Assert.areEqual("0,1,0,0", specificity.toString()); + + }, + + testSpecificity12: function(){ + var parser = new Parser(), + selector = parser.parseSelector("body #foo .foo p"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(112, specificity.valueOf()); + Assert.areEqual("0,1,1,2", specificity.toString()); + + }, + + testSpecificity13: function(){ + var parser = new Parser(), + selector = parser.parseSelector("#s12:not(FOO)"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(101, specificity.valueOf()); + Assert.areEqual("0,1,0,1", specificity.toString()); + + } + + + })); + + +})(); +(function(){ + + var Assert = YUITest.Assert, + TokenStream = parserlib.css.TokenStream, + CSSTokens = parserlib.css.Tokens; + + //------------------------------------------------------------------------- + // New testcase type to make it easier to test patterns + //------------------------------------------------------------------------- + + function CSSTokenTestCase(info){ + + YUITest.TestCase.call(this, info); + this.patterns = info.patterns; + + for (var prop in this.patterns){ + if (this.patterns.hasOwnProperty(prop)){ + this["testPattern: " + prop] = function(prop){ + return function(){ + this._testPattern(prop, this.patterns[prop]); + }; + }(prop); + } + } + } + + CSSTokenTestCase.prototype = new YUITest.TestCase(); + + CSSTokenTestCase.prototype._testPattern = function(pattern, outputs){ + var tokenStream = new TokenStream(pattern, CSSTokens); + var tt; + + for (var i=0, len=outputs.length; i < len; i++){ + tt = tokenStream.get((outputs[i] > -1 ? CSSTokens[outputs[i]].channel : undefined)); + Assert.areEqual(outputs[i], tt, "Token type should be " + CSSTokens.name(outputs[i]) + " but was " + CSSTokens.name(tt) + " (" + ( tokenStream.token() ? tokenStream.token().value : "unknown") + ")."); + } + + //if there was an invalid token, stop here + if (tt > -1){ + tt = tokenStream.get(); + Assert.areEqual(CSSTokens.EOF, tt, "Expected end of input but found token " + CSSTokens.name(tt) + " (" + ( tokenStream.token() ? tokenStream.token().value : "unknown") + ")."); + } + }; + + + + + + //------------------------------------------------------------------------- + // Simple CSS token tests + //------------------------------------------------------------------------- + + var suite = new YUITest.TestSuite("CSS Tokens"); + + + //note: \r\n is normalized to just \n by StringReader + suite.add(new CSSTokenTestCase({ + name : "Tests for Whitespace", + + patterns: { + " " : [CSSTokens.S], + "\n" : [CSSTokens.S], + "\n \t" : [CSSTokens.S], + "\f \n" : [CSSTokens.S] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for comments", + + patterns: { + //"/* booya */" : [], + //"/*\n booya */" : [], + //"/*\n booya \n*/" : [], + //"/*/*/" : [], + "/*/hello*/abc" : [CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for comparison operators", + + patterns: { + "~=": [CSSTokens.INCLUDES], + "|=": [CSSTokens.DASHMATCH], + "^=": [CSSTokens.PREFIXMATCH], + "$=": [CSSTokens.SUFFIXMATCH], + "*=": [CSSTokens.SUBSTRINGMATCH] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for identifiers", + + patterns: { + "a": [CSSTokens.IDENT], + "ab": [CSSTokens.IDENT], + "a1": [CSSTokens.IDENT], + "a_c": [CSSTokens.IDENT], + "a-c": [CSSTokens.IDENT], + "a90": [CSSTokens.IDENT], + "a\\09": [CSSTokens.IDENT], + "\\sa": [CSSTokens.IDENT], + + //not identifiers + "9a": [CSSTokens.DIMENSION] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for strings", + + patterns: { + "'hello'" : [CSSTokens.STRING], + "\"hello\"" : [CSSTokens.STRING], + "''" : [CSSTokens.STRING], + "\"\"" : [CSSTokens.STRING], + "'hello\"" : [CSSTokens.INVALID], + "\"hello'" : [CSSTokens.INVALID], + "'hello" : [CSSTokens.INVALID], + "'hel\\\'lo'" : [CSSTokens.STRING], + "\"hel\\\"lo\"" : [CSSTokens.STRING] + } + })); + + + suite.add(new CSSTokenTestCase({ + name : "Tests for hashes", + + // need to use double \\ to represent a single \ due to escaping + patterns: { + "#identifier" : [CSSTokens.HASH], + "#_identifer" : [CSSTokens.HASH], + "#0-9_" : [CSSTokens.HASH], + "#name'" : [CSSTokens.HASH, CSSTokens.INVALID], + "#h\\0fllo" : [CSSTokens.HASH], + "#ffeeff" : [CSSTokens.HASH], + "#\\31 a2b3c" : [CSSTokens.HASH], + "#r0\\.5" : [CSSTokens.HASH] + } + })); + + //------------------------------------------------------------------------- + // Tests for at-rules + //------------------------------------------------------------------------- + + (function(){ + + var atRules = { + "@charset" : CSSTokens.CHARSET_SYM, + "@import" : CSSTokens.IMPORT_SYM, + "@page" : CSSTokens.PAGE_SYM, + "@media" : CSSTokens.MEDIA_SYM, + "@font-face" : CSSTokens.FONT_FACE_SYM, + "@namespace" : CSSTokens.NAMESPACE_SYM, + "@top-left-corner" : CSSTokens.TOPLEFTCORNER_SYM, + "@top-left" : CSSTokens.TOPLEFT_SYM, + "@top-right-corner" : CSSTokens.TOPRIGHTCORNER_SYM, + "@top-right" : CSSTokens.TOPRIGHT_SYM, + "@bottom-left-corner" : CSSTokens.BOTTOMLEFTCORNER_SYM, + "@bottom-left" : CSSTokens.BOTTOMLEFT_SYM, + "@bottom-right-corner" : CSSTokens.BOTTOMRIGHTCORNER_SYM, + "@bottom-right" : CSSTokens.BOTTOMRIGHT_SYM, + "@left-top" : CSSTokens.LEFTTOP_SYM, + "@left-middle" : CSSTokens.LEFTMIDDLE_SYM, + "@left-bottom" : CSSTokens.LEFTBOTTOM_SYM, + "@right-top" : CSSTokens.RIGHTTOP_SYM, + "@right-middle" : CSSTokens.RIGHTMIDDLE_SYM, + "@right-bottom" : CSSTokens.RIGHTBOTTOM_SYM, + + //animation + "@-webkit-keyframes": CSSTokens.KEYFRAMES_SYM, + "@-moz-keyframes" : CSSTokens.KEYFRAMES_SYM, + "@keyframes" : CSSTokens.KEYFRAMES_SYM, + + //errors + "@foo" : CSSTokens.UNKNOWN_SYM, + "@bar" : CSSTokens.UNKNOWN_SYM + }; + + var patterns; + + for (var prop in atRules){ + patterns = {}; + + patterns[prop] = [atRules[prop]]; + patterns[prop + " "] = [atRules[prop], CSSTokens.S]; + patterns[prop.toUpperCase()] = [atRules[prop]]; + patterns[prop.toUpperCase() + " "] = [atRules[prop], CSSTokens.S]; + + suite.add(new CSSTokenTestCase({ + name: "Tests for " + prop, + patterns: patterns + })); + } + })(); + + + suite.add(new CSSTokenTestCase({ + name : "Tests for !important", + + patterns: { + "!important" : [CSSTokens.IMPORTANT_SYM], + "!IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "! important" : [CSSTokens.IMPORTANT_SYM], + "! IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "!/*booya*/important" : [CSSTokens.IMPORTANT_SYM], + "!/*booya*/IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "! /*booya*/ important" : [CSSTokens.IMPORTANT_SYM], + "! /*booya*/ IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + + //bogus symbols + "! /*IMPORTANT" : [CSSTokens.CHAR, CSSTokens.S, CSSTokens.EOF], + "! / important" : [CSSTokens.CHAR, CSSTokens.S, CSSTokens.SLASH, CSSTokens.S, CSSTokens.IDENT], + "!IMPO RTANT" : [CSSTokens.CHAR, CSSTokens.IDENT, CSSTokens.S, CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for HTML-style comments", + + patterns: { + "" : [CSSTokens.CDC], + "--> " : [CSSTokens.CDC, CSSTokens.S] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Unicode ranges", + + patterns: { + "U+A5" : [CSSTokens.UNICODE_RANGE], + "U+0-7F" : [CSSTokens.UNICODE_RANGE], + "U+590-5ff" : [CSSTokens.UNICODE_RANGE], + "U+AB-BC" : [CSSTokens.UNICODE_RANGE], + "U+4E00-9FFF" : [CSSTokens.UNICODE_RANGE], + "U+30??" : [CSSTokens.UNICODE_RANGE], + "U+00-FF" : [CSSTokens.UNICODE_RANGE], + "U+??????" : [CSSTokens.UNICODE_RANGE], + "U+0??????" : [CSSTokens.UNICODE_RANGE, CSSTokens.CHAR], + "U+00-??" : [CSSTokens.UNICODE_RANGE, CSSTokens.MINUS, CSSTokens.CHAR, CSSTokens.CHAR], + "U+?1" : [CSSTokens.UNICODE_RANGE, CSSTokens.NUMBER], + "U+" : [CSSTokens.CHAR, CSSTokens.PLUS], + "U+00-J" : [CSSTokens.UNICODE_RANGE, CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for :not", + + patterns: { + ":not(" : [CSSTokens.NOT], + ":noT(" : [CSSTokens.NOT], + ":nOT(" : [CSSTokens.NOT], + ":NOT(" : [CSSTokens.NOT], + ":not " : [CSSTokens.COLON, CSSTokens.IDENT, CSSTokens.S], + "button:not([DISABLED])": [CSSTokens.IDENT, CSSTokens.NOT, CSSTokens.LBRACKET, CSSTokens.IDENT, CSSTokens.RBRACKET, CSSTokens.RPAREN] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Media Queries", + + patterns: { + "not" : [CSSTokens.IDENT], + "and" : [CSSTokens.IDENT], + "only" : [CSSTokens.IDENT], + "5dpi" : [CSSTokens.RESOLUTION], + "5.2dPi": [CSSTokens.RESOLUTION], + ".5DPI" : [CSSTokens.RESOLUTION] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Numbers", + + patterns: { + + + //pixels + "4px" : [CSSTokens.LENGTH], + "50.0PX" : [CSSTokens.LENGTH], + ".6Px" : [CSSTokens.LENGTH], + + + "7cm" : [CSSTokens.LENGTH], + "7CM" : [CSSTokens.LENGTH], + "7cM" : [CSSTokens.LENGTH], + "8.0mm" : [CSSTokens.LENGTH], + ".9in" : [CSSTokens.LENGTH], + "7pc" : [CSSTokens.LENGTH], + "8.0pt" : [CSSTokens.LENGTH], + + "5em" : [CSSTokens.LENGTH], + "50.0EM" : [CSSTokens.LENGTH], + ".5eM" : [CSSTokens.LENGTH], + + "5ex" : [CSSTokens.LENGTH], + "50.0EX" : [CSSTokens.LENGTH], + ".5eX" : [CSSTokens.LENGTH], + + "5vw" : [CSSTokens.LENGTH], + "50.0VW" : [CSSTokens.LENGTH], + ".5vW" : [CSSTokens.LENGTH], + + "5vh" : [CSSTokens.LENGTH], + "50.0VH" : [CSSTokens.LENGTH], + ".5vH" : [CSSTokens.LENGTH], + + "5rem" : [CSSTokens.LENGTH], + "50.0REM" : [CSSTokens.LENGTH], + ".5rEm" : [CSSTokens.LENGTH], + + "5vm" : [CSSTokens.LENGTH], + "50.0VM" : [CSSTokens.LENGTH], + ".5vM" : [CSSTokens.LENGTH], + + "5ch" : [CSSTokens.LENGTH], + "50.0CH" : [CSSTokens.LENGTH], + ".5cH" : [CSSTokens.LENGTH], + + + + "5deg" : [CSSTokens.ANGLE], + "50.0DEG" : [CSSTokens.ANGLE], + ".5Deg" : [CSSTokens.ANGLE], + + "5rad" : [CSSTokens.ANGLE], + "50.0RAD" : [CSSTokens.ANGLE], + ".5Rad" : [CSSTokens.ANGLE], + + "5grad" : [CSSTokens.ANGLE], + "50.0GRAD" : [CSSTokens.ANGLE], + ".5Grad" : [CSSTokens.ANGLE], + + "5ms" : [CSSTokens.TIME], + "50.0MS" : [CSSTokens.TIME], + ".5Ms" : [CSSTokens.TIME], + + "5s" : [CSSTokens.TIME], + "50.0S" : [CSSTokens.TIME], + + "5hz" : [CSSTokens.FREQ], + "50.0HZ" : [CSSTokens.FREQ], + ".5Hz" : [CSSTokens.FREQ], + + "5khz" : [CSSTokens.FREQ], + "50.0KHZ" : [CSSTokens.FREQ], + ".5kHz" : [CSSTokens.FREQ], + + "5ncz" : [CSSTokens.DIMENSION], + "50.0NCZ" : [CSSTokens.DIMENSION], + ".5nCz" : [CSSTokens.DIMENSION], + + "3%" : [CSSTokens.PERCENTAGE], + "45.05%" : [CSSTokens.PERCENTAGE], + ".9%" : [CSSTokens.PERCENTAGE], + + //regular numbers + "1" : [CSSTokens.NUMBER], + "20.0" : [CSSTokens.NUMBER], + ".3" : [CSSTokens.NUMBER], + + //invalid numbers + "-.3" : [CSSTokens.MINUS, CSSTokens.NUMBER], + "+0" : [CSSTokens.PLUS, CSSTokens.NUMBER], + "-name" : [CSSTokens.IDENT], + "+name" : [CSSTokens.PLUS, CSSTokens.IDENT] + + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for URLs", + + patterns: { + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url('https://github.com/foo.jpg')" : [CSSTokens.URI], + "url(https://github.com/%22foo.jpg/")" : [CSSTokens.URI], + + "url(http://www.nczonline.net/favicon.ico)": [CSSTokens.URI], + "url('http://www.nczonline.net/favicon.ico')": [CSSTokens.URI], + "url(https://github.com/%22http://www.nczonline.net/favicon.ico/")":[CSSTokens.URI], + + "url(http://www.nczonline.net/favicon.ico?a=b&c=d)": [CSSTokens.URI], + "url('http://www.nczonline.net/favicon.ico?a=b&c=d')": [CSSTokens.URI], + "url(https://github.com/%22http://www.nczonline.net/favicon.ico?a=b&c=d\")":[CSSTokens.URI], + + //invalid URLs + "url('https://github.com/booya/")" : [CSSTokens.FUNCTION, CSSTokens.INVALID], + "url('booya'" : [CSSTokens.FUNCTION, CSSTokens.STRING] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Functions", + + patterns: { + + //regular CSS functions + "rgb(255,0,1)" : [CSSTokens.FUNCTION, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.RPAREN], + "counter(par-num,upper-roman)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.RPAREN], + + //old-style IE filters - interpreted as bunch of tokens + "alpha(opacity=50)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN], + + //IE filters - not sure how to handle these yet + "progid:DXImageTransform.Microsoft.Wave(strength=100)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN], + "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN], + "progid:DXImageTransform.Microsoft.Iris(irisstyle='STAR', duration=4)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.STRING, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for single-character tokens", + + patterns: { + + //single characters with defined tokens + "/" : [CSSTokens.SLASH], + "-" : [CSSTokens.MINUS], + "+" : [CSSTokens.PLUS], + "*" : [CSSTokens.STAR], + ">" : [CSSTokens.GREATER], + "{" : [CSSTokens.LBRACE], + "}" : [CSSTokens.RBRACE], + "[" : [CSSTokens.LBRACKET], + "]" : [CSSTokens.RBRACKET], + "=" : [CSSTokens.EQUALS], + ":" : [CSSTokens.COLON], + ";" : [CSSTokens.SEMICOLON], + "(" : [CSSTokens.LPAREN], + ")" : [CSSTokens.RPAREN], + "." : [CSSTokens.DOT], + "," : [CSSTokens.COMMA], + + //single characters without tokens + "@" : [CSSTokens.CHAR] + } + })); + + //------------------------------------------------------------------------- + // More complex testing patterns + //------------------------------------------------------------------------- + + suite.add(new CSSTokenTestCase({ + name : "Tests for Properties", + + patterns: { + + //regular CSS functions + "background: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], + "background-color: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], + + "filter: progid:DXImageTransform.Microsoft.Wave(strength=100);": [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN, CSSTokens.SEMICOLON] + + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for odd cases", + + patterns: { + + //regular CSS functions + ".name" : [CSSTokens.DOT, CSSTokens.IDENT], + "-name" : [CSSTokens.IDENT] + + } + })); + + YUITest.TestRunner.add(suite); + +})(); diff --git a/build/parserlib.js b/build/parserlib.js index 83917e60..372d5f95 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:12:52 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/tests/css/Parser.js b/tests/css/Parser.js new file mode 100644 index 00000000..57936ca9 --- /dev/null +++ b/tests/css/Parser.js @@ -0,0 +1,1716 @@ +(function(){ + + var Assert = YUITest.Assert, + MediaQuery = parserlib.css.MediaQuery, + Selector = parserlib.css.Selector, + Combinator = parserlib.css.Combinator, + SelectorPart = parserlib.css.SelectorPart, + Parser = parserlib.css.Parser; + + //------------------------------------------------------------------------- + // Base Test Suite + //------------------------------------------------------------------------- + + var suite = new YUITest.TestSuite("Selector Parsing"); + + suite.add(new YUITest.TestCase({ + + name: "Type Selector Tests", + + testSimpleTypeSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(Parser.SELECTOR_TYPE, result.type); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual(Parser.SELECTOR_PART_TYPE, result.parts[0].type); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("svg|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(Parser.SELECTOR_TYPE, result.type); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("svg|rect", result.parts[0].elementName, "Element name should be 'svg|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusBlankNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("|rect", result.parts[0].elementName, "Element name should be '|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + }, + + testSimpleTypeSelectorPlusUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*|rect"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*|rect", result.parts[0].elementName, "Element name should be '*|rect'."); + Assert.areEqual(0, result.parts[0].modifiers, "Element should have zero modifiers."); + Assert.areEqual(1, result.specificity.valueOf()); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Universal Selector Tests", + + testSimpleUniversalSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*", result.parts[0].elementName, "Element name should be '*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("svg|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("svg|*", result.parts[0].elementName, "Element name should be 'svg|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusBlankNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("|*", result.parts[0].elementName, "Element name should be '|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + }, + + testSimpleUniversalSelectorPlusUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("*|*"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("*|*", result.parts[0].elementName, "Element name should be '*|*'."); + Assert.areEqual(0, result.parts[0].modifiers.length, "Element should have zero modifiers."); + Assert.areEqual(0, result.specificity.valueOf()); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "Attribute Selector Tests", + + testAttributePresenceSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class]", result.parts[0].modifiers[0].text, "Modifier text should be '[class]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEquivalenceSelectorNoString: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeContainsSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class~=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class~=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class~=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeDashMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[class|=\"selected\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[class|=\"selected\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[class|=\"selected\"]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeStartMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("object[type^=\"image/\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("object", result.parts[0].elementName, "Element name should be 'object'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[type^=\"image/\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[type^=\"image/\"]'."); + Assert.areEqual(7, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEndMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a[href$=\".html\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName, "Element name should be 'a'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[href$=\".html\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[href$=\".html\"]'."); + Assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeContainsMatchSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("p[title*=\"hello\"]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("p", result.parts[0].elementName, "Element name should be 'p'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[title*=\"hello\"]", result.parts[0].modifiers[0].text, "Modifier text should be '[title*=\"hello\"]'."); + Assert.areEqual(2, result.parts[0].modifiers[0].col, "Modifier column should be 2."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + }, + + testAttributeEquivalenceSelectorNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[html|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[html|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[html|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelectorUniversalNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[*|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[*|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[*|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + }, + + testAttributeEquivalenceSelectorDefaultNamespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li[|class=selected]"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be 'li'."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("attribute", result.parts[0].modifiers[0].type, "Modifier type should be 'attribute'."); + Assert.areEqual("[|class=selected]", result.parts[0].modifiers[0].text, "Modifier text should be '[|class=selected]'."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Modifier column should be 3."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line should be 1."); + Assert.areEqual(11, result.specificity.valueOf()); + + } + })); + + + suite.add(new YUITest.TestCase({ + + name: "Class Selector Tests", + + testSimpleClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector(".selected"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual(1, result.parts[0].line, "Line start should be 1"); + Assert.areEqual(1, result.parts[0].col, "Column start should be 1"); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + + }, + + testCompoundClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector(".selected.foo"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.line, "Line start should be 1"); + Assert.areEqual(1, result.col, "Column start should be 1"); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have two modifiers."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual("class", result.parts[0].modifiers[1].type, "Modifier type should be 'class'."); + Assert.areEqual(".foo", result.parts[0].modifiers[1].text, "Modifier text should be '.foo'."); + }, + + testSimpleClassSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.selected"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li",result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line start should be 1"); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Column start should be 3"); + + }, + + testCompoundClassSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.selected.foo"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have two modifiers."); + Assert.areEqual("class", result.parts[0].modifiers[0].type, "Modifier type should be 'class'."); + Assert.areEqual(".selected", result.parts[0].modifiers[0].text, "Modifier text should be '.selected'."); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "Line start should be 1"); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "Column start should be 3"); + Assert.areEqual("class", result.parts[0].modifiers[1].type, "Modifier type should be 'class'."); + Assert.areEqual(".foo", result.parts[0].modifiers[1].text, "Modifier text should be '.foo'."); + Assert.areEqual(1, result.parts[0].modifiers[1].line, "Line start should be 1"); + Assert.areEqual(12, result.parts[0].modifiers[1].col, "Column start should be 12"); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "ID Selector Tests", + + testSimpleIDSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("#header"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isNull(result.parts[0].elementName, "Element name should be null."); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("id", result.parts[0].modifiers[0].type, "Modifier type should be 'id'."); + Assert.areEqual("#header", result.parts[0].modifiers[0].text, "Modifier text should be '#header'."); + }, + + testSimpleIDSelectorWithElementName: function(){ + var parser = new Parser(); + var result = parser.parseSelector("div#header"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("div", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("id", result.parts[0].modifiers[0].type, "Modifier type should be 'id'."); + Assert.areEqual("#header", result.parts[0].modifiers[0].text, "Modifier text should be '#header'."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Pseudo Class Selector Tests", + + testSimplePseudoClassSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a:hover"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":hover", result.parts[0].modifiers[0].text, "Modifier text should be ':hover'."); + }, + + testMultiplePseudoClassSelectors: function(){ + var parser = new Parser(); + var result = parser.parseSelector("a:focus:hover"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("a", result.parts[0].elementName); + Assert.areEqual(2, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":focus", result.parts[0].modifiers[0].text, "Modifier text should be ':focus'."); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text, "Modifier text should be ':hover'."); + }, + + testPseudoClassFunctionSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("html:lang(fr-be)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("html", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":lang(fr-be)", result.parts[0].modifiers[0].text, "Modifier text should be ':lang(fr-be)'."); + }, + + testPseudoClassNthSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(2n+1)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(2n+1)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(2n+1)'."); + }, + + testPseudoClassNthSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(even)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(even)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(even)'."); + }, + + testPseudoClassNthSelector3: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(5)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-child(5)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-child(5)'."); + }, + + testPseudoClassNthSelector4: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-of-type(5)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":nth-of-type(5)", result.parts[0].modifiers[0].text, "Modifier text should be ':nth-of-type(5)'."); + }, + + testPseudoClassLastChildSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:last-child"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("tr", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":last-child", result.parts[0].modifiers[0].text, "Modifier text should be ':last-child'."); + }, + + testPseudoClassNotSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("button:not([DISABLED])"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("button", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("not", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":not([DISABLED])", result.parts[0].modifiers[0].text, "Modifier text should be ':not([DISABLED])'."); + Assert.areEqual(1, result.parts[0].modifiers[0].args.length, "Modifier should have one argument."); + + var arg = result.parts[0].modifiers[0].args[0]; + + Assert.isInstanceOf(SelectorPart, arg, "Result should be an instance of Selector."); + Assert.areEqual("[DISABLED]", arg.toString()); + Assert.isNull(arg.elementName); + Assert.areEqual(1, arg.modifiers.length); + Assert.areEqual("attribute", arg.modifiers[0].type); + }, + + testPseudoClassNotSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("button:not(foo)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("button", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("not", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual(":not(foo)", result.parts[0].modifiers[0].text, "Modifier text should be ':not(foo)'."); + Assert.areEqual(1, result.parts[0].modifiers[0].args.length, "Modifier should have one argument."); + + + var arg = result.parts[0].modifiers[0].args[0]; + + Assert.isInstanceOf(SelectorPart, arg, "Result should be an instance of Selector."); + Assert.areEqual("foo", arg.toString()); + Assert.areEqual("foo", arg.elementName, "Element name should be 'foo'."); + Assert.areEqual(0, arg.modifiers.length); + + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Pseudo Element Selector Tests", + + testSimplePseudoElementSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("p::first-line"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Selector should have one parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("p", result.parts[0].elementName); + Assert.areEqual(1, result.parts[0].modifiers.length, "Element should have one modifier."); + Assert.areEqual("pseudo", result.parts[0].modifiers[0].type, "Modifier type should be 'pseudo'."); + Assert.areEqual("::first-line", result.parts[0].modifiers[0].text, "Modifier text should be '::first-line'."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Combinators", + + + testChildCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover > p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorNoSpaces: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover>p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorOneSpaceBefore: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover >p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testChildCombinatorOneSpaceAfter: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover> p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(">", result.parts[1].text); + Assert.areEqual("child", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testAdjacentSiblingCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover + p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("+", result.parts[1].text); + Assert.areEqual("adjacent-sibling", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testGeneralSiblingCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover ~ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("~", result.parts[1].text); + Assert.areEqual("sibling", result.parts[1].type); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testDescendantCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(1, result.parts[0].modifiers[0].line, "The line should be 1."); + Assert.areEqual(3, result.parts[0].modifiers[0].col, "The column should be 3."); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.areEqual(1, result.parts[0].modifiers[1].line, "The line should be 1."); + Assert.areEqual(10, result.parts[0].modifiers[1].col, "The column should be 10."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(" ", result.parts[1].text); + Assert.areEqual("descendant", result.parts[1].type); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(16, result.parts[1].col, "Column should be 16."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + Assert.areEqual(1, result.parts[2].elementName.line, "Line should be 1."); + Assert.areEqual(17, result.parts[2].elementName.col, "Column should be 17."); + }, + + testDescendantCombinatorWithTrailingWhitespace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover p "); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].elementName); + Assert.areEqual(".inline", result.parts[0].modifiers[0].text); + Assert.areEqual("class", result.parts[0].modifiers[0].type); + Assert.areEqual(":hover", result.parts[0].modifiers[1].text); + Assert.areEqual("pseudo", result.parts[0].modifiers[1].type); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(" ", result.parts[1].text); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].elementName); + }, + + testWithCombinator: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li.inline:hover > p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(17, result.parts[1].col, "Column should be 17."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithNthChild: function(){ + var parser = new Parser(); + var result = parser.parseSelector("tr:nth-child(2n+1) a"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + } + + + //body > h2:nth-of-type(n+2):nth-last-of-type(n+2) + //body > h2:not(:first-of-type):not(:last-of-type) + //html|*:not(:link):not(:visited) + })); + + suite.add(new YUITest.TestCase({ + + name: "Complex Cases", + + testWithComplexSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("body > h2:nth-of-type(n+2):nth-last-of-type(n+2)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(6, result.parts[1].col, "Column should be 6."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual(1, result.parts[2].line, "Line should be 1."); + Assert.areEqual(8, result.parts[2].col, "Column should be 8."); + }, + + testWithComplexSelector2: function(){ + var parser = new Parser(); + var result = parser.parseSelector("body > h2:not(:first-of-type):not(:last-of-type)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithComplexSelector3: function(){ + var parser = new Parser(); + var result = parser.parseSelector("html|*:not(:link):not(:visited)"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(1, result.parts.length, "Should be one part."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + //Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + //Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + }, + + testWithMultipartSelector: function(){ + var parser = new Parser(); + var result = parser.parseSelector("ul li a span"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.areEqual(7, result.parts.length, "Should be four parts."); + + Assert.isInstanceOf(SelectorPart, result.parts[0], "Part should be a SelectorPart."); + Assert.areEqual("ul", result.parts[0].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[2], "Part should be a SelectorPart."); + Assert.areEqual("li", result.parts[2].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[4], "Part should be a SelectorPart."); + Assert.areEqual("a", result.parts[4].elementName); + + Assert.isInstanceOf(SelectorPart, result.parts[6], "Part should be a SelectorPart."); + Assert.areEqual("span", result.parts[6].elementName); + + } + + + + })); + + + suite.add(new YUITest.TestCase({ + + name: "Media Queries", + + + testSimpleMediaQuery: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.isNull(result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testSimpleMediaQueryNot: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("not print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("not", result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testSimpleMediaQueryOnly: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("only print"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("only", result.modifier); + Assert.areEqual("print", result.mediaType); + Assert.areEqual(0, result.features.length, "Should be zero parts."); + }, + + testComplexMediaQuery: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("screen and (max-weight: 3kg) and (color)"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.isNull(result.modifier); + Assert.areEqual("screen", result.mediaType); + Assert.areEqual(2, result.features.length, "Should be two features."); + Assert.areEqual("max-weight", result.features[0].name); + Assert.areEqual(25, result.features[0].value.col); + Assert.areEqual("3kg", result.features[0].value); + Assert.areEqual("color", result.features[1].name); + Assert.isNull(result.features[1].value); + Assert.areEqual(35, result.features[1].name.col); + + }, + + testComplexMediaQuery2: function(){ + var parser = new Parser(); + var result = parser.parseMediaQuery("only screen and (max-device-width: 768px) and (orientation:portrait)"); + + Assert.isInstanceOf(MediaQuery, result, "Result should be an instance of MediaQuery."); + Assert.areEqual(1, result.line, "Line should be 1"); + Assert.areEqual(1, result.col, "Column should be 1"); + Assert.areEqual("only", result.modifier); + Assert.areEqual("screen", result.mediaType); + Assert.areEqual(2, result.features.length, "Should be two features."); + Assert.areEqual("max-device-width", result.features[0].name); + Assert.areEqual("768px", result.features[0].value); + Assert.areEqual("orientation", result.features[1].name); + Assert.areEqual("portrait", result.features[1].value); + } + + + })); + + + suite.add(new YUITest.TestCase({ + + name: "Property Values", + + testDimensionValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("1px"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(1, result.parts[0].value); + Assert.areEqual("px", result.parts[0].units); + }, + + testPercentageValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25.4%"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("percentage", result.parts[0].type); + Assert.areEqual(25.4, result.parts[0].value); + }, + + testIntegerValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("integer", result.parts[0].type); + Assert.areEqual(25, result.parts[0].value); + }, + + testNumberValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("25.0"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("number", result.parts[0].type); + Assert.areEqual(25, result.parts[0].value); + }, + + testHexColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("#ffeedd"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + }, + + testRGBColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgb(255, 238 , 221)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + }, + + testRGBColorValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgb(100%,50%, 75%)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(127.5, result.parts[0].green); + Assert.areEqual(191.25, result.parts[0].blue); + }, + + testRGBAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(255, 238 , 221, 0.3)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(238, result.parts[0].green); + Assert.areEqual(221, result.parts[0].blue); + Assert.areEqual(0.3, result.parts[0].alpha); + }, + + testRGBAColorValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("rgba(100%,50%, 75%, 0.5)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(127.5, result.parts[0].green); + Assert.areEqual(191.25, result.parts[0].blue); + Assert.areEqual(0.5, result.parts[0].alpha); + }, + + testHSLColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsl(100,50%, 75%)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(100, result.parts[0].hue); + Assert.areEqual(0.5, result.parts[0].saturation); + Assert.areEqual(0.75, result.parts[0].lightness); + }, + + testHSLAColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("hsla(100,50%, 75%, 0.5)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(100, result.parts[0].hue); + Assert.areEqual(0.5, result.parts[0].saturation); + Assert.areEqual(0.75, result.parts[0].lightness); + Assert.areEqual(0.5, result.parts[0].alpha); + }, + + testColorValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("red"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("color", result.parts[0].type); + Assert.areEqual(255, result.parts[0].red); + Assert.areEqual(0, result.parts[0].green); + Assert.areEqual(0, result.parts[0].blue); + }, + + testURIValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url(http://www.yahoo.com/)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testURIValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url('http://www.yahoo.com/')"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testURIValue3: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("url(https://github.com/%22http://www.yahoo.com/")"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("uri", result.parts[0].type); + Assert.areEqual("http://www.yahoo.com/", result.parts[0].uri); + }, + + testStringValue: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("'Hello world!'"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("string", result.parts[0].type); + Assert.areEqual("Hello world!", result.parts[0].value); + }, + + testStringValue2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("\"Hello world!\""); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("string", result.parts[0].type); + Assert.areEqual("Hello world!", result.parts[0].value); + }, + + testValueWithOperators: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("10px / 1em"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(3, result.parts.length); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[0]); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(10, result.parts[0].value); + Assert.areEqual("px", result.parts[0].units); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[1]); + Assert.areEqual("operator", result.parts[1].type); + Assert.areEqual("/", result.parts[1].text); + Assert.areEqual(1, result.parts[1].line, "Line should be 1."); + Assert.areEqual(6, result.parts[1].col, "Column should be 6."); + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[2]); + Assert.areEqual("length", result.parts[2].type); + Assert.areEqual(1, result.parts[2].value); + Assert.areEqual("em", result.parts[2].units); + }, + + testValueWithOperators2: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("1em/1.5em \"Times New Roman\", Times, serif"); + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(8, result.parts.length); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[0]); + Assert.areEqual("length", result.parts[0].type); + Assert.areEqual(1, result.parts[0].value); + Assert.areEqual("em", result.parts[0].units); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[1]); + Assert.areEqual("operator", result.parts[1].type); + Assert.areEqual("/", result.parts[1].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[2]); + Assert.areEqual("length", result.parts[2].type); + Assert.areEqual(1.5, result.parts[2].value); + Assert.areEqual("em", result.parts[2].units); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[3]); + Assert.areEqual("string", result.parts[3].type); + Assert.areEqual("Times New Roman", result.parts[3].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[4]); + Assert.areEqual("operator", result.parts[4].type); + Assert.areEqual(",", result.parts[4].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[5]); + Assert.areEqual("identifier", result.parts[5].type); + Assert.areEqual("Times", result.parts[5].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[6]); + Assert.areEqual("operator", result.parts[6].type); + Assert.areEqual(",", result.parts[6].value); + + Assert.isInstanceOf(parserlib.css.PropertyValuePart, result.parts[7]); + Assert.areEqual("identifier", result.parts[7].type); + Assert.areEqual("serif", result.parts[7].value); + } + + + + })); + + suite.add(new YUITest.TestCase({ + + name: "Rules", + + testRuleWithOnePartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithTwoPartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithThreePartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li a{ color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + }, + + testRuleWithFourPartSelector: function(){ + var parser = new Parser(); + var result = parser.parseRule("p li a span { color: red; }"); + + Assert.isObject(result, "Parse should have completed."); + } + })); + + suite.add(new YUITest.TestCase({ + + name: "Special Cases", + + _should: { + error: { + testIEFilter5: "Unexpected token '=' at line 1, col 14." + } + }, + + testWithCommentAndSpaces: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li /*booya*/ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testWithCommentAndTrailingSpace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li/*booya*/ p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testWithCommentAndLeadingSpace: function(){ + var parser = new Parser(); + var result = parser.parseSelector("li /*booya*/p"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("li", result.parts[0].toString(), "First part should be 'li'"); + Assert.isInstanceOf(Combinator, result.parts[1], "Second part should be a Combinator."); + Assert.areEqual("descendant", result.parts[1].type, "Second part should be a 'descendant'"); + Assert.isInstanceOf(SelectorPart, result.parts[2], "Third part should be a SelectorPart."); + Assert.areEqual("p", result.parts[2].toString(), "First part should be 'p'"); + Assert.areEqual(3, result.parts.length, "Should be three parts."); + }, + + testIEFilter: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.Wave(strength=100)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + }, + + testIEFilter2: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=http://l.yimg.com/ne/home/metro/pa/map/gugimap_btn_mapview.png, sizingMethod=image)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + + }, + + testIEFilter3: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', src='http://l.yimg.com/ne/home/metro/pa/map/gugimap_btn_mapview.png', sizingMethod='image')"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("unknown", result.parts[0].type); + + }, + + testIEFilter4: function(){ + var parser = new Parser({ieFilters:true}); + var result = parser.parsePropertyValue("alpha(opacity=10)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + Assert.areEqual(1, result.parts.length); + Assert.areEqual("alpha(opacity=10)", result.text); + Assert.areEqual("unknown", result.parts[0].type); + }, + + testIEFilter5: function(){ + var parser = new Parser(); + var result = parser.parsePropertyValue("alpha(opacity=10)"); + + Assert.isInstanceOf(parserlib.css.PropertyValue, result); + } + + + + + })); + + suite.add(new YUITest.TestCase({ + + name: "Animation Parsing Tests", + + testWebKitKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@-webkit-keyframes movingbox{0%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testMozKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@-moz-keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFrames: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFramesFromTo: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes movingbox{from{left:90%;-webkit-transform: rotate(0deg);}to{left:10%;-webkit-transform: rotate(360deg);}}"); + Assert.isTrue(true); //just don't want an error + }, + + testKeyFramesWithWhitespace: function(){ + var parser = new Parser({strict:true}); + var result = parser.parse("@keyframes 'diagonal-slide' { from { left: 0; top: 0; } to { left: 100px; top: 100px; } }"); + Assert.isTrue(true); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "General Parsing Tests", + + testMediaWithPage: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media { @page {} }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithTypeOnly: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media print { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithTypesOnly: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media print, screen { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithSimpleExpression: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media (max-width:400px) { }"); + Assert.isTrue(true); //just don't want an error + }, + + testMediaWithComplexExpression: function(){ + var parser = new Parser({ strict: true}); + var result = parser.parse("@media all and (max-width:400px) { }"); + Assert.isTrue(true); //just don't want an error + }, + + testClassesWithEscapes: function(){ + var parser = new Parser({strict:true}); + var result = parser.parseSelector("#\\31 a2b3c"); + + Assert.isInstanceOf(Selector, result, "Result should be an instance of Selector."); + Assert.isInstanceOf(SelectorPart, result.parts[0], "First part should be a SelectorPart."); + Assert.areEqual("#\\31 a2b3c", result.parts[0].toString(), "Selector should be correct."); + Assert.areEqual(1, result.parts.length, "Should be one part."); + } + + })); + + suite.add(new YUITest.TestCase({ + + name: "Validation Tests", + + testInvalidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected color or one of (inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: foo; }"); + + }, + + testInvalidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected color or one of (inherit) but found 'invert'.", event.invalid.message); + }); + var result = parser.parse(".foo { color: invert; }"); + + }, + + testValidColor: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: red; }"); + + }, + + testValidColor2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: #ff0000; }"); + + }, + + testValidColor3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { color: inherit; }"); + + }, + + testValidColor4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-color: transparent; }"); + + }, + + testBackgroundAttachment1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: scroll; }"); + + }, + + testBackgroundAttachment2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: fixed; }"); + + }, + + testBackgroundAttachment3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-attachment: local; }"); + + }, + + testInvalidBackgroundAttachment: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected attachment but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { background-attachment: foo; }"); + }, + + testInvalidZIndex: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected integer or one of (auto | inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { z-index: foo; }"); + }, + + testZIndex1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: 1 }"); + + }, + + testZIndex2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: auto }"); + }, + + testZIndex3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { z-index: inherit }"); + + }, + + testBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px }"); + + }, + + testBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px }"); + + }, + + testBorderWidth3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px}"); + + }, + + testBorderWidth4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected a max of 4 property values but found 5.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: 1px 1px 1px 1px 1px}"); + + }, + + testInvalidBorderWidth2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected border-width but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { border-width: foo}"); + + }, + + testMinHeight1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1px; }"); + + }, + + testMinHeight2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: 1%; }"); + + }, + + testMinHeight3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { min-height: inherit; }"); + + }, + + testInvalidMinHeight: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected length or percentage or one of (inherit) but found 'foo'.", event.invalid.message); + }); + var result = parser.parse(".foo { min-height: foo}"); + + }, + + testOpacity: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { opacity: 1}"); + + }, + + testBackgroundImage1: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: none}"); + }, + + testBackgroundImage2: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png)}"); + }, + + testBackgroundImage3: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), none}"); + }, + + testBackgroundImage4: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNull(event.invalid); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png), url(https://github.com/bar.png)}"); + }, + + testBackgroundImage5: function(){ + var parser = new Parser({ strict: true}); + parser.addListener("property", function(event){ + Assert.isNotNull(event.invalid); + Assert.areEqual("Expected end of line but found ','.", event.invalid.message); + }); + var result = parser.parse(".foo { background-image: url(https://github.com/foo.png),}"); + } + + })); + + + YUITest.TestRunner.add(suite); + +})(); diff --git a/tests/css/Specificity.js b/tests/css/Specificity.js new file mode 100644 index 00000000..fb1a79ba --- /dev/null +++ b/tests/css/Specificity.js @@ -0,0 +1,142 @@ +(function(){ + + var Assert = YUITest.Assert, + Parser = parserlib.css.Parser, + Specificity = parserlib.css.Specificity; + + YUITest.TestRunner.add(new YUITest.TestCase({ + + name: "Specificity Tests", + + testSpecificity1: function(){ + var parser = new Parser(), + selector = parser.parseSelector("*"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(0, specificity.valueOf()); + Assert.areEqual("0,0,0,0", specificity.toString()); + }, + + testSpecificity2: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(1, specificity.valueOf()); + Assert.areEqual("0,0,0,1", specificity.toString()); + }, + + testSpecificity3: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li:first-line"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(2, specificity.valueOf()); + Assert.areEqual("0,0,0,2", specificity.toString()); + }, + + testSpecificity4: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(2, specificity.valueOf()); + Assert.areEqual("0,0,0,2", specificity.toString()); + + }, + + testSpecificity5: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul ol+li"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(3, specificity.valueOf()); + Assert.areEqual("0,0,0,3", specificity.toString()); + + }, + + testSpecificity6: function(){ + var parser = new Parser(), + selector = parser.parseSelector("h1 + *[rel=up]"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(11, specificity.valueOf()); + Assert.areEqual("0,0,1,1", specificity.toString()); + + }, + + testSpecificity7: function(){ + var parser = new Parser(), + selector = parser.parseSelector("ul ol li.red"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(13, specificity.valueOf()); + Assert.areEqual("0,0,1,3", specificity.toString()); + + }, + + testSpecificity8: function(){ + var parser = new Parser(), + selector = parser.parseSelector("li.red.level"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(21, specificity.valueOf()); + Assert.areEqual("0,0,2,1", specificity.toString()); + + }, + + testSpecificity9: function(){ + var parser = new Parser(), + selector = parser.parseSelector(".f00"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(10, specificity.valueOf()); + Assert.areEqual("0,0,1,0", specificity.toString()); + + }, + + testSpecificity10: function(){ + var parser = new Parser(), + selector = parser.parseSelector("div p.foo"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(12, specificity.valueOf()); + Assert.areEqual("0,0,1,2", specificity.toString()); + + }, + + testSpecificity11: function(){ + var parser = new Parser(), + selector = parser.parseSelector("#foo"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(100, specificity.valueOf()); + Assert.areEqual("0,1,0,0", specificity.toString()); + + }, + + testSpecificity12: function(){ + var parser = new Parser(), + selector = parser.parseSelector("body #foo .foo p"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(112, specificity.valueOf()); + Assert.areEqual("0,1,1,2", specificity.toString()); + + }, + + testSpecificity13: function(){ + var parser = new Parser(), + selector = parser.parseSelector("#s12:not(FOO)"), + specificity = Specificity.calculate(selector); + + Assert.areEqual(101, specificity.valueOf()); + Assert.areEqual("0,1,0,1", specificity.toString()); + + } + + + })); + + +})(); \ No newline at end of file diff --git a/tests/css/TokenStream.js b/tests/css/TokenStream.js new file mode 100644 index 00000000..6bf8153c --- /dev/null +++ b/tests/css/TokenStream.js @@ -0,0 +1,479 @@ +(function(){ + + var Assert = YUITest.Assert, + TokenStream = parserlib.css.TokenStream, + CSSTokens = parserlib.css.Tokens; + + //------------------------------------------------------------------------- + // New testcase type to make it easier to test patterns + //------------------------------------------------------------------------- + + function CSSTokenTestCase(info){ + + YUITest.TestCase.call(this, info); + this.patterns = info.patterns; + + for (var prop in this.patterns){ + if (this.patterns.hasOwnProperty(prop)){ + this["testPattern: " + prop] = function(prop){ + return function(){ + this._testPattern(prop, this.patterns[prop]); + }; + }(prop); + } + } + } + + CSSTokenTestCase.prototype = new YUITest.TestCase(); + + CSSTokenTestCase.prototype._testPattern = function(pattern, outputs){ + var tokenStream = new TokenStream(pattern, CSSTokens); + var tt; + + for (var i=0, len=outputs.length; i < len; i++){ + tt = tokenStream.get((outputs[i] > -1 ? CSSTokens[outputs[i]].channel : undefined)); + Assert.areEqual(outputs[i], tt, "Token type should be " + CSSTokens.name(outputs[i]) + " but was " + CSSTokens.name(tt) + " (" + ( tokenStream.token() ? tokenStream.token().value : "unknown") + ")."); + } + + //if there was an invalid token, stop here + if (tt > -1){ + tt = tokenStream.get(); + Assert.areEqual(CSSTokens.EOF, tt, "Expected end of input but found token " + CSSTokens.name(tt) + " (" + ( tokenStream.token() ? tokenStream.token().value : "unknown") + ")."); + } + }; + + + + + + //------------------------------------------------------------------------- + // Simple CSS token tests + //------------------------------------------------------------------------- + + var suite = new YUITest.TestSuite("CSS Tokens"); + + + //note: \r\n is normalized to just \n by StringReader + suite.add(new CSSTokenTestCase({ + name : "Tests for Whitespace", + + patterns: { + " " : [CSSTokens.S], + "\n" : [CSSTokens.S], + "\n \t" : [CSSTokens.S], + "\f \n" : [CSSTokens.S] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for comments", + + patterns: { + //"/* booya */" : [], + //"/*\n booya */" : [], + //"/*\n booya \n*/" : [], + //"/*/*/" : [], + "/*/hello*/abc" : [CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for comparison operators", + + patterns: { + "~=": [CSSTokens.INCLUDES], + "|=": [CSSTokens.DASHMATCH], + "^=": [CSSTokens.PREFIXMATCH], + "$=": [CSSTokens.SUFFIXMATCH], + "*=": [CSSTokens.SUBSTRINGMATCH] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for identifiers", + + patterns: { + "a": [CSSTokens.IDENT], + "ab": [CSSTokens.IDENT], + "a1": [CSSTokens.IDENT], + "a_c": [CSSTokens.IDENT], + "a-c": [CSSTokens.IDENT], + "a90": [CSSTokens.IDENT], + "a\\09": [CSSTokens.IDENT], + "\\sa": [CSSTokens.IDENT], + + //not identifiers + "9a": [CSSTokens.DIMENSION] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for strings", + + patterns: { + "'hello'" : [CSSTokens.STRING], + "\"hello\"" : [CSSTokens.STRING], + "''" : [CSSTokens.STRING], + "\"\"" : [CSSTokens.STRING], + "'hello\"" : [CSSTokens.INVALID], + "\"hello'" : [CSSTokens.INVALID], + "'hello" : [CSSTokens.INVALID], + "'hel\\\'lo'" : [CSSTokens.STRING], + "\"hel\\\"lo\"" : [CSSTokens.STRING] + } + })); + + + suite.add(new CSSTokenTestCase({ + name : "Tests for hashes", + + // need to use double \\ to represent a single \ due to escaping + patterns: { + "#identifier" : [CSSTokens.HASH], + "#_identifer" : [CSSTokens.HASH], + "#0-9_" : [CSSTokens.HASH], + "#name'" : [CSSTokens.HASH, CSSTokens.INVALID], + "#h\\0fllo" : [CSSTokens.HASH], + "#ffeeff" : [CSSTokens.HASH], + "#\\31 a2b3c" : [CSSTokens.HASH], + "#r0\\.5" : [CSSTokens.HASH] + } + })); + + //------------------------------------------------------------------------- + // Tests for at-rules + //------------------------------------------------------------------------- + + (function(){ + + var atRules = { + "@charset" : CSSTokens.CHARSET_SYM, + "@import" : CSSTokens.IMPORT_SYM, + "@page" : CSSTokens.PAGE_SYM, + "@media" : CSSTokens.MEDIA_SYM, + "@font-face" : CSSTokens.FONT_FACE_SYM, + "@namespace" : CSSTokens.NAMESPACE_SYM, + "@top-left-corner" : CSSTokens.TOPLEFTCORNER_SYM, + "@top-left" : CSSTokens.TOPLEFT_SYM, + "@top-right-corner" : CSSTokens.TOPRIGHTCORNER_SYM, + "@top-right" : CSSTokens.TOPRIGHT_SYM, + "@bottom-left-corner" : CSSTokens.BOTTOMLEFTCORNER_SYM, + "@bottom-left" : CSSTokens.BOTTOMLEFT_SYM, + "@bottom-right-corner" : CSSTokens.BOTTOMRIGHTCORNER_SYM, + "@bottom-right" : CSSTokens.BOTTOMRIGHT_SYM, + "@left-top" : CSSTokens.LEFTTOP_SYM, + "@left-middle" : CSSTokens.LEFTMIDDLE_SYM, + "@left-bottom" : CSSTokens.LEFTBOTTOM_SYM, + "@right-top" : CSSTokens.RIGHTTOP_SYM, + "@right-middle" : CSSTokens.RIGHTMIDDLE_SYM, + "@right-bottom" : CSSTokens.RIGHTBOTTOM_SYM, + + //animation + "@-webkit-keyframes": CSSTokens.KEYFRAMES_SYM, + "@-moz-keyframes" : CSSTokens.KEYFRAMES_SYM, + "@keyframes" : CSSTokens.KEYFRAMES_SYM, + + //errors + "@foo" : CSSTokens.UNKNOWN_SYM, + "@bar" : CSSTokens.UNKNOWN_SYM + }; + + var patterns; + + for (var prop in atRules){ + patterns = {}; + + patterns[prop] = [atRules[prop]]; + patterns[prop + " "] = [atRules[prop], CSSTokens.S]; + patterns[prop.toUpperCase()] = [atRules[prop]]; + patterns[prop.toUpperCase() + " "] = [atRules[prop], CSSTokens.S]; + + suite.add(new CSSTokenTestCase({ + name: "Tests for " + prop, + patterns: patterns + })); + } + })(); + + + suite.add(new CSSTokenTestCase({ + name : "Tests for !important", + + patterns: { + "!important" : [CSSTokens.IMPORTANT_SYM], + "!IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "! important" : [CSSTokens.IMPORTANT_SYM], + "! IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "!/*booya*/important" : [CSSTokens.IMPORTANT_SYM], + "!/*booya*/IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + "! /*booya*/ important" : [CSSTokens.IMPORTANT_SYM], + "! /*booya*/ IMPORTANT" : [CSSTokens.IMPORTANT_SYM], + + //bogus symbols + "! /*IMPORTANT" : [CSSTokens.CHAR, CSSTokens.S, CSSTokens.EOF], + "! / important" : [CSSTokens.CHAR, CSSTokens.S, CSSTokens.SLASH, CSSTokens.S, CSSTokens.IDENT], + "!IMPO RTANT" : [CSSTokens.CHAR, CSSTokens.IDENT, CSSTokens.S, CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for HTML-style comments", + + patterns: { + "" : [CSSTokens.CDC], + "--> " : [CSSTokens.CDC, CSSTokens.S] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Unicode ranges", + + patterns: { + "U+A5" : [CSSTokens.UNICODE_RANGE], + "U+0-7F" : [CSSTokens.UNICODE_RANGE], + "U+590-5ff" : [CSSTokens.UNICODE_RANGE], + "U+AB-BC" : [CSSTokens.UNICODE_RANGE], + "U+4E00-9FFF" : [CSSTokens.UNICODE_RANGE], + "U+30??" : [CSSTokens.UNICODE_RANGE], + "U+00-FF" : [CSSTokens.UNICODE_RANGE], + "U+??????" : [CSSTokens.UNICODE_RANGE], + "U+0??????" : [CSSTokens.UNICODE_RANGE, CSSTokens.CHAR], + "U+00-??" : [CSSTokens.UNICODE_RANGE, CSSTokens.MINUS, CSSTokens.CHAR, CSSTokens.CHAR], + "U+?1" : [CSSTokens.UNICODE_RANGE, CSSTokens.NUMBER], + "U+" : [CSSTokens.CHAR, CSSTokens.PLUS], + "U+00-J" : [CSSTokens.UNICODE_RANGE, CSSTokens.IDENT] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for :not", + + patterns: { + ":not(" : [CSSTokens.NOT], + ":noT(" : [CSSTokens.NOT], + ":nOT(" : [CSSTokens.NOT], + ":NOT(" : [CSSTokens.NOT], + ":not " : [CSSTokens.COLON, CSSTokens.IDENT, CSSTokens.S], + "button:not([DISABLED])": [CSSTokens.IDENT, CSSTokens.NOT, CSSTokens.LBRACKET, CSSTokens.IDENT, CSSTokens.RBRACKET, CSSTokens.RPAREN] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Media Queries", + + patterns: { + "not" : [CSSTokens.IDENT], + "and" : [CSSTokens.IDENT], + "only" : [CSSTokens.IDENT], + "5dpi" : [CSSTokens.RESOLUTION], + "5.2dPi": [CSSTokens.RESOLUTION], + ".5DPI" : [CSSTokens.RESOLUTION] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Numbers", + + patterns: { + + + //pixels + "4px" : [CSSTokens.LENGTH], + "50.0PX" : [CSSTokens.LENGTH], + ".6Px" : [CSSTokens.LENGTH], + + + "7cm" : [CSSTokens.LENGTH], + "7CM" : [CSSTokens.LENGTH], + "7cM" : [CSSTokens.LENGTH], + "8.0mm" : [CSSTokens.LENGTH], + ".9in" : [CSSTokens.LENGTH], + "7pc" : [CSSTokens.LENGTH], + "8.0pt" : [CSSTokens.LENGTH], + + "5em" : [CSSTokens.LENGTH], + "50.0EM" : [CSSTokens.LENGTH], + ".5eM" : [CSSTokens.LENGTH], + + "5ex" : [CSSTokens.LENGTH], + "50.0EX" : [CSSTokens.LENGTH], + ".5eX" : [CSSTokens.LENGTH], + + "5vw" : [CSSTokens.LENGTH], + "50.0VW" : [CSSTokens.LENGTH], + ".5vW" : [CSSTokens.LENGTH], + + "5vh" : [CSSTokens.LENGTH], + "50.0VH" : [CSSTokens.LENGTH], + ".5vH" : [CSSTokens.LENGTH], + + "5rem" : [CSSTokens.LENGTH], + "50.0REM" : [CSSTokens.LENGTH], + ".5rEm" : [CSSTokens.LENGTH], + + "5vm" : [CSSTokens.LENGTH], + "50.0VM" : [CSSTokens.LENGTH], + ".5vM" : [CSSTokens.LENGTH], + + "5ch" : [CSSTokens.LENGTH], + "50.0CH" : [CSSTokens.LENGTH], + ".5cH" : [CSSTokens.LENGTH], + + + + "5deg" : [CSSTokens.ANGLE], + "50.0DEG" : [CSSTokens.ANGLE], + ".5Deg" : [CSSTokens.ANGLE], + + "5rad" : [CSSTokens.ANGLE], + "50.0RAD" : [CSSTokens.ANGLE], + ".5Rad" : [CSSTokens.ANGLE], + + "5grad" : [CSSTokens.ANGLE], + "50.0GRAD" : [CSSTokens.ANGLE], + ".5Grad" : [CSSTokens.ANGLE], + + "5ms" : [CSSTokens.TIME], + "50.0MS" : [CSSTokens.TIME], + ".5Ms" : [CSSTokens.TIME], + + "5s" : [CSSTokens.TIME], + "50.0S" : [CSSTokens.TIME], + + "5hz" : [CSSTokens.FREQ], + "50.0HZ" : [CSSTokens.FREQ], + ".5Hz" : [CSSTokens.FREQ], + + "5khz" : [CSSTokens.FREQ], + "50.0KHZ" : [CSSTokens.FREQ], + ".5kHz" : [CSSTokens.FREQ], + + "5ncz" : [CSSTokens.DIMENSION], + "50.0NCZ" : [CSSTokens.DIMENSION], + ".5nCz" : [CSSTokens.DIMENSION], + + "3%" : [CSSTokens.PERCENTAGE], + "45.05%" : [CSSTokens.PERCENTAGE], + ".9%" : [CSSTokens.PERCENTAGE], + + //regular numbers + "1" : [CSSTokens.NUMBER], + "20.0" : [CSSTokens.NUMBER], + ".3" : [CSSTokens.NUMBER], + + //invalid numbers + "-.3" : [CSSTokens.MINUS, CSSTokens.NUMBER], + "+0" : [CSSTokens.PLUS, CSSTokens.NUMBER], + "-name" : [CSSTokens.IDENT], + "+name" : [CSSTokens.PLUS, CSSTokens.IDENT] + + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for URLs", + + patterns: { + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url(https://github.com/foo.jpg)" : [CSSTokens.URI], + "url('https://github.com/foo.jpg')" : [CSSTokens.URI], + "url(https://github.com/%22foo.jpg/")" : [CSSTokens.URI], + + "url(http://www.nczonline.net/favicon.ico)": [CSSTokens.URI], + "url('http://www.nczonline.net/favicon.ico')": [CSSTokens.URI], + "url(https://github.com/%22http://www.nczonline.net/favicon.ico/")":[CSSTokens.URI], + + "url(http://www.nczonline.net/favicon.ico?a=b&c=d)": [CSSTokens.URI], + "url('http://www.nczonline.net/favicon.ico?a=b&c=d')": [CSSTokens.URI], + "url(https://github.com/%22http://www.nczonline.net/favicon.ico?a=b&c=d\")":[CSSTokens.URI], + + //invalid URLs + "url('https://github.com/booya/")" : [CSSTokens.FUNCTION, CSSTokens.INVALID], + "url('booya'" : [CSSTokens.FUNCTION, CSSTokens.STRING] + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for Functions", + + patterns: { + + //regular CSS functions + "rgb(255,0,1)" : [CSSTokens.FUNCTION, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.NUMBER, CSSTokens.RPAREN], + "counter(par-num,upper-roman)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.COMMA, CSSTokens.IDENT, CSSTokens.RPAREN], + + //old-style IE filters - interpreted as bunch of tokens + "alpha(opacity=50)" : [CSSTokens.FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN], + + //IE filters - not sure how to handle these yet + "progid:DXImageTransform.Microsoft.Wave(strength=100)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN], + "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN], + "progid:DXImageTransform.Microsoft.Iris(irisstyle='STAR', duration=4)" : [CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.STRING, CSSTokens.COMMA, CSSTokens.S, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER,CSSTokens.RPAREN] + } + })); + + suite.add(new CSSTokenTestCase({ + name: "Test for single-character tokens", + + patterns: { + + //single characters with defined tokens + "/" : [CSSTokens.SLASH], + "-" : [CSSTokens.MINUS], + "+" : [CSSTokens.PLUS], + "*" : [CSSTokens.STAR], + ">" : [CSSTokens.GREATER], + "{" : [CSSTokens.LBRACE], + "}" : [CSSTokens.RBRACE], + "[" : [CSSTokens.LBRACKET], + "]" : [CSSTokens.RBRACKET], + "=" : [CSSTokens.EQUALS], + ":" : [CSSTokens.COLON], + ";" : [CSSTokens.SEMICOLON], + "(" : [CSSTokens.LPAREN], + ")" : [CSSTokens.RPAREN], + "." : [CSSTokens.DOT], + "," : [CSSTokens.COMMA], + + //single characters without tokens + "@" : [CSSTokens.CHAR] + } + })); + + //------------------------------------------------------------------------- + // More complex testing patterns + //------------------------------------------------------------------------- + + suite.add(new CSSTokenTestCase({ + name : "Tests for Properties", + + patterns: { + + //regular CSS functions + "background: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], + "background-color: red;" : [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IDENT, CSSTokens.SEMICOLON], + + "filter: progid:DXImageTransform.Microsoft.Wave(strength=100);": [CSSTokens.IDENT, CSSTokens.COLON, CSSTokens.S, CSSTokens.IE_FUNCTION, CSSTokens.IDENT, CSSTokens.EQUALS, CSSTokens.NUMBER, CSSTokens.RPAREN, CSSTokens.SEMICOLON] + + } + })); + + suite.add(new CSSTokenTestCase({ + name : "Tests for odd cases", + + patterns: { + + //regular CSS functions + ".name" : [CSSTokens.DOT, CSSTokens.IDENT], + "-name" : [CSSTokens.IDENT] + + } + })); + + YUITest.TestRunner.add(suite); + +})(); From 9e8c9930b22604486a11a8275cf46194f55855fc Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 17 Nov 2011 10:40:13 -0800 Subject: [PATCH 026/313] More test cleanup --- build/node-parserlib.js | 4 +- build/parserlib-core.js | 2 +- build/parserlib-css.js | 2 +- build/parserlib-tests.js | 309 ++++++++++++++++++ build/parserlib.js | 4 +- .../util/StringReader.js | 113 +++---- 6 files changed, 355 insertions(+), 79 deletions(-) rename src/util/StringReaderTests.htm => tests/util/StringReader.js (73%) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 5a4c0f3d..283673f7 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 729830c4..770a6583 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 8fce3c9d..69ce1a56 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/build/parserlib-tests.js b/build/parserlib-tests.js index 7fccf557..36bb91ba 100644 --- a/build/parserlib-tests.js +++ b/build/parserlib-tests.js @@ -2335,3 +2335,312 @@ YUITest.TestRunner.add(suite); })(); +(function(){ + + var Assert = YUITest.Assert + StringReader = parserlib.util.StringReader; + + //------------------------------------------------------------------------- + // Base Test Suite + //------------------------------------------------------------------------- + + var suite = new YUITest.TestSuite("StringReader"); + + //------------------------------------------------------------------------- + // Test Case for adding + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "read() Tests", + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that reading a string with no new lines works. + */ + testLinearReadWithOneLine: function(){ + var testString = "Hello world!", + reader = new StringReader(testString), + i = 0, + c; + + Assert.areEqual(1, reader.getCol(), "Column should be 1."); + c = reader.read(); + + while(c){ + Assert.areEqual(testString.charAt(i), c, "Character at position " + i + " is incorrect."); + Assert.areEqual(i+2, reader.getCol(), "Column should be " + (i+2) + "."); + c = reader.read(); + i++; + } + + Assert.areEqual(testString.length, i, "All characters should be read."); + Assert.isNull(c, "Last character read should be null."); + }, + + /* + * Tests that reading a multi-line string works. + */ + testLinearReadWithTwoLines: function(){ + var testString = "Hello world!\nNice day, isn't it?", + reader = new StringReader(testString), + i = 0, + c = reader.read(); + + while(c){ + Assert.areEqual(testString.charAt(i), c, "Character at position " + i + " is incorrect."); + if (c == "\n"){ + Assert.areEqual(2, reader.getLine(), "Should now be on second row."); + Assert.areEqual(1, reader.getCol(), "The new line should cause you to go to first char in second row."); + } + c = reader.read(); + i++; + } + + Assert.isNull(c, "Last character read should be null."); + }, + + + /* + * Tests that reading a multi-line string properly tracks rows and cols. + */ + testLinearReadWithTwoLinesTrackCols: function(){ + var testString = "Hello world!\nNice day, isn't it?", + reader = new StringReader(testString); + + reader.readTo("!"); + reader.read(); + + Assert.areEqual(1, reader.getCol()); + Assert.areEqual(2, reader.getLine()); + + }, + + /* + * Tests that reading a multi-line string works when the last character is a new-line. + */ + testLinearReadWithTwoLinesAndDanglingNewLine: function(){ + var testString = "Hello world!\nNice day, isn't it?\n", + reader = new StringReader(testString), + i = 0, + c = reader.read(); + + while(c){ + Assert.areEqual(testString.charAt(i), c, "Character at position " + i + " is incorrect."); + c = reader.read(); + i++; + } + + Assert.isNull(c, "Last character read should be null."); + } + + + + + })); + + //------------------------------------------------------------------------- + // Test Case for readTo + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "readTo() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that reading a string with no new lines works. + */ + testLinearReadToWithOneLine: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + + Assert.areEqual("Hello ", reader.readTo(" ")); + Assert.areEqual("w", reader.read()); + }, + + /* + * Tests that reading a multi-line string works. + */ + testLinearReadToWithTwoLines: function(){ + var testString = "Hello world!\nNice day, isn't it?", + reader = new StringReader(testString); + + + Assert.areEqual("Hello world!\nN", reader.readTo("N")); + Assert.areEqual(2, reader.getLine()); + Assert.areEqual(2, reader.getCol()); + } + + })); + + //------------------------------------------------------------------------- + // Test Case for readWhile() + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "readWhile() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that the entire string can be read.. + */ + testReadWhileSimple: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + var result = reader.readWhile(function(){ + return true; + }); + + Assert.areEqual(testString, result); + Assert.areEqual(1, reader.getLine()); + Assert.areEqual(13, reader.getCol()); + } + })); + + //------------------------------------------------------------------------- + // Test Case for readCount() + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "readCount() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that a set number of characters are read correctly. + */ + testReadCountSimple: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + var result = reader.readCount(6); + + Assert.areEqual("Hello ", result); + + result = reader.readCount(2); + Assert.areEqual("wo", result); + } + })); + + //------------------------------------------------------------------------- + // Test Case for readMatch() + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "readMatch() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that a text pattern is read correctly. + */ + testReadMatchSimple: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + var result = reader.readMatch("Hello"); + + Assert.areEqual("Hello", result); + }, + + /* + * Tests that a regex pattern is read correctly. + */ + testReadMatchRegEx: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + var result = reader.readMatch(/^Hello/); + + Assert.areEqual("Hello", result); + } + + + })); + + + + //------------------------------------------------------------------------- + // Test Case for eof() + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "eof() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that eof() works after reading to end of string. + */ + testTestEofSimple: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + reader.readTo("!"); + Assert.isTrue(reader.eof()); + } + + + })); + + //------------------------------------------------------------------------- + // Test Case for mark() and reset() + //------------------------------------------------------------------------- + + suite.add(new YUITest.TestCase({ + + name : "mark() and reset() Tests", + + + //--------------------------------------------------------------------- + // Tests + //--------------------------------------------------------------------- + + /* + * Tests that mark() and reset() preserve lines/cols correctly. + */ + testMarkResetSimple: function(){ + var testString = "Hello world!", + reader = new StringReader(testString); + + reader.mark(); + reader.readTo("!"); + reader.reset(); + + Assert.areEqual(1, reader.getLine(), "Row should be 1"); + Assert.areEqual(1, reader.getCol(), "Column should be 1"); + } + + + })); + + YUITest.TestRunner.add(suite); + +})(); diff --git a/build/parserlib.js b/build/parserlib.js index 372d5f95..72ddb12b 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:36:14 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, diff --git a/src/util/StringReaderTests.htm b/tests/util/StringReader.js similarity index 73% rename from src/util/StringReaderTests.htm rename to tests/util/StringReader.js index b82e1faf..5b60591f 100644 --- a/src/util/StringReaderTests.htm +++ b/tests/util/StringReader.js @@ -1,36 +1,19 @@ - - - -String Reader Tests - - - - - - - - - -

String Reader Tests

- - - From 4fd72363c0d6531024bc1c70535e76432724a894 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 17 Nov 2011 10:56:36 -0800 Subject: [PATCH 027/313] Fixed specificity error --- build/node-parserlib.js | 21 +++++++++++++++++---- build/parserlib-core.js | 2 +- build/parserlib-css.js | 19 ++++++++++++++++--- build/parserlib.js | 21 +++++++++++++++++---- src/css/Specificity.js | 3 ++- 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 283673f7..6326acf5 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3380,8 +3380,20 @@ Parser.prototype = function(){ //otherwise return result return result; + }, + + /** + * Parses an HTML style attribute: a set of CSS declarations + * separated by semicolons. + * @param {String} input The text to parse as a style attribute + * @return {void} + * @method parseStyleAttribute + */ + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); } - }; //copy over onto prototype @@ -4368,9 +4380,10 @@ Specificity.calculate = function(selector){ function updateValues(part){ var i, j, len, num, + elementName = part.elementName ? part.elementName.text : "", modifier; - if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + if (elementName && elementName.charAt(elementName.length-1) != "*") { d++; } diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 770a6583..81cf7ddd 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 69ce1a56..3bbaa97a 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -2475,8 +2475,20 @@ Parser.prototype = function(){ //otherwise return result return result; + }, + + /** + * Parses an HTML style attribute: a set of CSS declarations + * separated by semicolons. + * @param {String} input The text to parse as a style attribute + * @return {void} + * @method parseStyleAttribute + */ + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); } - }; //copy over onto prototype @@ -3463,9 +3475,10 @@ Specificity.calculate = function(selector){ function updateValues(part){ var i, j, len, num, + elementName = part.elementName ? part.elementName.text : "", modifier; - if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + if (elementName && elementName.charAt(elementName.length-1) != "*") { d++; } diff --git a/build/parserlib.js b/build/parserlib.js index 72ddb12b..3b33f7ea 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:39:21 */ +/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -3380,8 +3380,20 @@ Parser.prototype = function(){ //otherwise return result return result; + }, + + /** + * Parses an HTML style attribute: a set of CSS declarations + * separated by semicolons. + * @param {String} input The text to parse as a style attribute + * @return {void} + * @method parseStyleAttribute + */ + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); } - }; //copy over onto prototype @@ -4368,9 +4380,10 @@ Specificity.calculate = function(selector){ function updateValues(part){ var i, j, len, num, + elementName = part.elementName ? part.elementName.text : "", modifier; - if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + if (elementName && elementName.charAt(elementName.length-1) != "*") { d++; } diff --git a/src/css/Specificity.js b/src/css/Specificity.js index d13ca268..fd270296 100644 --- a/src/css/Specificity.js +++ b/src/css/Specificity.js @@ -76,9 +76,10 @@ Specificity.calculate = function(selector){ function updateValues(part){ var i, j, len, num, + elementName = part.elementName ? part.elementName.text : "", modifier; - if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + if (elementName && elementName.charAt(elementName.length-1) != "*") { d++; } From 86259cfab58f5075263cf150d0b19d5e7c21311b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 18 Nov 2011 08:19:51 -0800 Subject: [PATCH 028/313] Refactored validation code --- build/node-parserlib.js | 396 ++-- build/parserlib-core.js | 2 +- build/parserlib-css.js | 394 ++-- build/parserlib-tests.js | 2 +- build/parserlib.js | 396 ++-- lib/yuitest.js | 4561 ++++++++++++++++++++++++++++++++++++++ src/css/Parser.js | 17 +- src/css/Properties.js | 200 +- src/css/Validation.js | 177 ++ tests/css/Parser.js | 2 +- tests/testrunner.htm | 137 ++ 11 files changed, 5423 insertions(+), 861 deletions(-) create mode 100644 lib/yuitest.js create mode 100644 src/css/Validation.js create mode 100644 tests/testrunner.htm diff --git a/build/node-parserlib.js b/build/node-parserlib.js index 6326acf5..7f5044e9 100644 --- a/build/node-parserlib.js +++ b/build/node-parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1189,7 +1189,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; -/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, +/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit, PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ @@ -3267,20 +3267,7 @@ Parser.prototype = function(){ // Validation methods //----------------------------------------------------------------- _validateProperty: function(property, value){ - var name = property.text.toLowerCase(), - validation, - i, len; - - if (Properties[name]){ - - if (typeof Properties[name] == "function"){ - Properties[name](value); - } - - //otherwise, no validation available yet - } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); - } + Validation.validate(property, value); }, //----------------------------------------------------------------- @@ -3413,101 +3400,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -//This file will likely change a lot! Very experimental! -/*global ValidationError*/ - -var ValidationType = { - - "absolute-size": function(part){ - return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); - }, - - "attachment": function(part){ - return this.identifier(part, "scroll | fixed | local"); - }, - - "box": function(part){ - return this.identifier(part, "padding-box | border-box | content-box"); - }, - - "relative-size": function(part){ - return this.identifier(part, "smaller | larger"); - }, - - "identifier": function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - "length": function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - "color": function(part){ - return part.type == "color" || part == "transparent"; - }, - - "number": function(part){ - return part.type == "number" || this.integer(part); - }, - - "integer": function(part){ - return part.type == "integer"; - }, - - "angle": function(part){ - return part.type == "angle"; - }, - - "uri": function(part){ - return part.type == "uri"; - }, - - "image": function(part){ - return this.uri(part); - }, - - "bg-image": function(part){ - return this.image(part) || part == "none"; - }, - - "percentage": function(part){ - return part.type == "percentage" || part == "0"; - }, - - "border-width": function(part){ - return this.length(part) || this.identifier(part, "thin | medium | thick"); - }, - - "border-style": function(part){ - return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - "margin-width": function(part){ - return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); - }, - - "padding-width": function(part){ - return this.length(part) || this.percentage(part); - } -}; - - - - - - - var Properties = { //A @@ -3846,109 +3738,6 @@ var Properties = { "z-index": [ "integer", "auto | inherit" ], "zoom": [ "number", "percentage", "normal" ] }; - -//Create validation functions for strings -(function(){ - var prop; - for (prop in Properties){ - if (Properties.hasOwnProperty(prop)){ - if (Properties[prop] instanceof Array){ - Properties[prop] = (function(values){ - return function(value){ - var valid = false, - msg = [], - part = value.parts[0]; - - if (value.parts.length != 1){ - throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); - } - - for (var i=0, len=values.length; i < len && !valid; i++){ - if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || ValidationType.identifier(part, values[i]); - msg.push("one of (" + values[i] + ")"); - } else { - valid = valid || ValidationType[values[i]](part); - msg.push(values[i]); - } - } - - if (!valid){ - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); - } - }; - })(Properties[prop]); - } else if (typeof Properties[prop] == "object"){ - Properties[prop] = (function(spec){ - return function(value){ - var valid, - i, len, j, count, - msg, - values, - last, - parts = value.parts; - - //if there's a maximum set, use it (max can't be 0) - if (spec.max) { - if (parts.length > spec.max){ - throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); - } - } - - if (spec.multi){ - values = spec.multi; - } - - for (i=0, len=parts.length; i < len; i++){ - msg = []; - valid = false; - - if (spec.separator && parts[i].type == "operator"){ - - //two operators in a row - not allowed? - if ((last && last.type == "operator")){ - msg = msg.concat(values); - } else if (i == len-1){ - msg = msg.concat("end of line"); - } else if (parts[i] != spec.separator){ - msg.push("'" + spec.separator + "'"); - } else { - valid = true; - } - } else { - - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); - } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } - } - } - - - if (!valid) { - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); - } - - - last = parts[i]; - } - - }; - })(Properties[prop]); - } - } - } -})(); /*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). @@ -5632,6 +5421,183 @@ var Tokens = [ +//This file will likely change a lot! Very experimental! +/*global Properties, ValidationError*/ +var Validation = { + + validate: function(property, value){ + + //normalize name + var name = property.toString().toLowerCase(), + valid, + spec = Properties[name], + i, len, j, count, + msg, + types, + last, + max, multi, + parts = value.parts; + + if (!spec) { + if (name.indexOf("-") !== 0){ //vendor prefixed are ok + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); + } + } else if (typeof spec != "number"){ + + //initialization + if (spec instanceof Array){ + types = spec; + max = 1; + } else if (spec.multi) { + types = spec.multi; + max = spec.max; + } + + //Start validation---- + + //if there's a maximum set, use it (max can't be 0) + if (max) { + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property value(s) but found " + parts.length + ".", value.line, value.col); + } + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(types); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); + } else { + valid = true; + } + } else { + + for (j=0, count=types.length; j < count; j++){ + if (typeof Validation.types[types[j]] == "undefined"){ + if(Validation.types.identifier(parts[i], types[j])){ + valid = true; + break; + } + msg.push("one of (" + types[j] + ")"); + } else { + if (Validation.types[types[j]](parts[i])){ + valid = true; + break; + } + msg.push(types[j]); + } + } + } + + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + + + last = parts[i]; + } + + + + } + }, + + types: { + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return this.length(part) || this.identifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } + } + +}; /** * Type to use when a validation error occurs. * @class ValidationError diff --git a/build/parserlib-core.js b/build/parserlib-core.js index 81cf7ddd..6a241e15 100644 --- a/build/parserlib-core.js +++ b/build/parserlib-core.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ var parserlib = {}; (function(){ diff --git a/build/parserlib-css.js b/build/parserlib-css.js index 3bbaa97a..69b43d94 100644 --- a/build/parserlib-css.js +++ b/build/parserlib-css.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -284,7 +284,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; -/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, +/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit, PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ @@ -2362,20 +2362,7 @@ Parser.prototype = function(){ // Validation methods //----------------------------------------------------------------- _validateProperty: function(property, value){ - var name = property.text.toLowerCase(), - validation, - i, len; - - if (Properties[name]){ - - if (typeof Properties[name] == "function"){ - Properties[name](value); - } - - //otherwise, no validation available yet - } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); - } + Validation.validate(property, value); }, //----------------------------------------------------------------- @@ -2508,101 +2495,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -//This file will likely change a lot! Very experimental! -/*global ValidationError*/ - -var ValidationType = { - - "absolute-size": function(part){ - return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); - }, - - "attachment": function(part){ - return this.identifier(part, "scroll | fixed | local"); - }, - - "box": function(part){ - return this.identifier(part, "padding-box | border-box | content-box"); - }, - - "relative-size": function(part){ - return this.identifier(part, "smaller | larger"); - }, - - "identifier": function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - "length": function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - "color": function(part){ - return part.type == "color" || part == "transparent"; - }, - - "number": function(part){ - return part.type == "number" || this.integer(part); - }, - - "integer": function(part){ - return part.type == "integer"; - }, - - "angle": function(part){ - return part.type == "angle"; - }, - - "uri": function(part){ - return part.type == "uri"; - }, - - "image": function(part){ - return this.uri(part); - }, - - "bg-image": function(part){ - return this.image(part) || part == "none"; - }, - - "percentage": function(part){ - return part.type == "percentage" || part == "0"; - }, - - "border-width": function(part){ - return this.length(part) || this.identifier(part, "thin | medium | thick"); - }, - - "border-style": function(part){ - return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - "margin-width": function(part){ - return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); - }, - - "padding-width": function(part){ - return this.length(part) || this.percentage(part); - } -}; - - - - - - - var Properties = { //A @@ -2941,109 +2833,6 @@ var Properties = { "z-index": [ "integer", "auto | inherit" ], "zoom": [ "number", "percentage", "normal" ] }; - -//Create validation functions for strings -(function(){ - var prop; - for (prop in Properties){ - if (Properties.hasOwnProperty(prop)){ - if (Properties[prop] instanceof Array){ - Properties[prop] = (function(values){ - return function(value){ - var valid = false, - msg = [], - part = value.parts[0]; - - if (value.parts.length != 1){ - throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); - } - - for (var i=0, len=values.length; i < len && !valid; i++){ - if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || ValidationType.identifier(part, values[i]); - msg.push("one of (" + values[i] + ")"); - } else { - valid = valid || ValidationType[values[i]](part); - msg.push(values[i]); - } - } - - if (!valid){ - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); - } - }; - })(Properties[prop]); - } else if (typeof Properties[prop] == "object"){ - Properties[prop] = (function(spec){ - return function(value){ - var valid, - i, len, j, count, - msg, - values, - last, - parts = value.parts; - - //if there's a maximum set, use it (max can't be 0) - if (spec.max) { - if (parts.length > spec.max){ - throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); - } - } - - if (spec.multi){ - values = spec.multi; - } - - for (i=0, len=parts.length; i < len; i++){ - msg = []; - valid = false; - - if (spec.separator && parts[i].type == "operator"){ - - //two operators in a row - not allowed? - if ((last && last.type == "operator")){ - msg = msg.concat(values); - } else if (i == len-1){ - msg = msg.concat("end of line"); - } else if (parts[i] != spec.separator){ - msg.push("'" + spec.separator + "'"); - } else { - valid = true; - } - } else { - - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); - } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } - } - } - - - if (!valid) { - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); - } - - - last = parts[i]; - } - - }; - })(Properties[prop]); - } - } - } -})(); /*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). @@ -4727,6 +4516,183 @@ var Tokens = [ +//This file will likely change a lot! Very experimental! +/*global Properties, ValidationError*/ +var Validation = { + + validate: function(property, value){ + + //normalize name + var name = property.toString().toLowerCase(), + valid, + spec = Properties[name], + i, len, j, count, + msg, + types, + last, + max, multi, + parts = value.parts; + + if (!spec) { + if (name.indexOf("-") !== 0){ //vendor prefixed are ok + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); + } + } else if (typeof spec != "number"){ + + //initialization + if (spec instanceof Array){ + types = spec; + max = 1; + } else if (spec.multi) { + types = spec.multi; + max = spec.max; + } + + //Start validation---- + + //if there's a maximum set, use it (max can't be 0) + if (max) { + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property value(s) but found " + parts.length + ".", value.line, value.col); + } + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(types); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); + } else { + valid = true; + } + } else { + + for (j=0, count=types.length; j < count; j++){ + if (typeof Validation.types[types[j]] == "undefined"){ + if(Validation.types.identifier(parts[i], types[j])){ + valid = true; + break; + } + msg.push("one of (" + types[j] + ")"); + } else { + if (Validation.types[types[j]](parts[i])){ + valid = true; + break; + } + msg.push(types[j]); + } + } + } + + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + + + last = parts[i]; + } + + + + } + }, + + types: { + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return this.length(part) || this.identifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } + } + +}; /** * Type to use when a validation error occurs. * @class ValidationError diff --git a/build/parserlib-tests.js b/build/parserlib-tests.js index 36bb91ba..3f34d847 100644 --- a/build/parserlib-tests.js +++ b/build/parserlib-tests.js @@ -1605,7 +1605,7 @@ var parser = new Parser({ strict: true}); parser.addListener("property", function(event){ Assert.isNotNull(event.invalid); - Assert.areEqual("Expected a max of 4 property values but found 5.", event.invalid.message); + Assert.areEqual("Expected a max of 4 property value(s) but found 5.", event.invalid.message); }); var result = parser.parse(".foo { border-width: 1px 1px 1px 1px 1px}"); diff --git a/build/parserlib.js b/build/parserlib.js index 3b33f7ea..a598aea4 100644 --- a/build/parserlib.js +++ b/build/parserlib.js @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ var parserlib = {}; (function(){ @@ -926,7 +926,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v@VERSION@, Build time: 17-November-2011 10:55:53 */ +/* Version v@VERSION@, Build time: 18-November-2011 08:17:14 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -1189,7 +1189,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; -/*global Tokens, TokenStream, SyntaxError, Properties, ValidationError, SyntaxUnit, +/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit, PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ @@ -3267,20 +3267,7 @@ Parser.prototype = function(){ // Validation methods //----------------------------------------------------------------- _validateProperty: function(property, value){ - var name = property.text.toLowerCase(), - validation, - i, len; - - if (Properties[name]){ - - if (typeof Properties[name] == "function"){ - Properties[name](value); - } - - //otherwise, no validation available yet - } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok - throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); - } + Validation.validate(property, value); }, //----------------------------------------------------------------- @@ -3413,101 +3400,6 @@ nth ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* ; */ -//This file will likely change a lot! Very experimental! -/*global ValidationError*/ - -var ValidationType = { - - "absolute-size": function(part){ - return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); - }, - - "attachment": function(part){ - return this.identifier(part, "scroll | fixed | local"); - }, - - "box": function(part){ - return this.identifier(part, "padding-box | border-box | content-box"); - }, - - "relative-size": function(part){ - return this.identifier(part, "smaller | larger"); - }, - - "identifier": function(part, options){ - var text = part.text.toString().toLowerCase(), - args = options.split(" | "), - i, len, found = false; - - - for (i=0,len=args.length; i < len && !found; i++){ - if (text == args[i]){ - found = true; - } - } - - return found; - }, - - "length": function(part){ - return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; - }, - - "color": function(part){ - return part.type == "color" || part == "transparent"; - }, - - "number": function(part){ - return part.type == "number" || this.integer(part); - }, - - "integer": function(part){ - return part.type == "integer"; - }, - - "angle": function(part){ - return part.type == "angle"; - }, - - "uri": function(part){ - return part.type == "uri"; - }, - - "image": function(part){ - return this.uri(part); - }, - - "bg-image": function(part){ - return this.image(part) || part == "none"; - }, - - "percentage": function(part){ - return part.type == "percentage" || part == "0"; - }, - - "border-width": function(part){ - return this.length(part) || this.identifier(part, "thin | medium | thick"); - }, - - "border-style": function(part){ - return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); - }, - - "margin-width": function(part){ - return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); - }, - - "padding-width": function(part){ - return this.length(part) || this.percentage(part); - } -}; - - - - - - - var Properties = { //A @@ -3846,109 +3738,6 @@ var Properties = { "z-index": [ "integer", "auto | inherit" ], "zoom": [ "number", "percentage", "normal" ] }; - -//Create validation functions for strings -(function(){ - var prop; - for (prop in Properties){ - if (Properties.hasOwnProperty(prop)){ - if (Properties[prop] instanceof Array){ - Properties[prop] = (function(values){ - return function(value){ - var valid = false, - msg = [], - part = value.parts[0]; - - if (value.parts.length != 1){ - throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); - } - - for (var i=0, len=values.length; i < len && !valid; i++){ - if (typeof ValidationType[values[i]] == "undefined"){ - valid = valid || ValidationType.identifier(part, values[i]); - msg.push("one of (" + values[i] + ")"); - } else { - valid = valid || ValidationType[values[i]](part); - msg.push(values[i]); - } - } - - if (!valid){ - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); - } - }; - })(Properties[prop]); - } else if (typeof Properties[prop] == "object"){ - Properties[prop] = (function(spec){ - return function(value){ - var valid, - i, len, j, count, - msg, - values, - last, - parts = value.parts; - - //if there's a maximum set, use it (max can't be 0) - if (spec.max) { - if (parts.length > spec.max){ - throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); - } - } - - if (spec.multi){ - values = spec.multi; - } - - for (i=0, len=parts.length; i < len; i++){ - msg = []; - valid = false; - - if (spec.separator && parts[i].type == "operator"){ - - //two operators in a row - not allowed? - if ((last && last.type == "operator")){ - msg = msg.concat(values); - } else if (i == len-1){ - msg = msg.concat("end of line"); - } else if (parts[i] != spec.separator){ - msg.push("'" + spec.separator + "'"); - } else { - valid = true; - } - } else { - - for (j=0, count=values.length; j < count; j++){ - if (typeof ValidationType[values[j]] == "undefined"){ - if(ValidationType.identifier(parts[i], values[j])){ - valid = true; - break; - } - msg.push("one of (" + values[j] + ")"); - } else { - if (ValidationType[values[j]](parts[i])){ - valid = true; - break; - } - msg.push(values[j]); - } - } - } - - - if (!valid) { - throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); - } - - - last = parts[i]; - } - - }; - })(Properties[prop]); - } - } - } -})(); /*global SyntaxUnit, Parser*/ /** * Represents a selector combinator (whitespace, +, >). @@ -5632,6 +5421,183 @@ var Tokens = [ +//This file will likely change a lot! Very experimental! +/*global Properties, ValidationError*/ +var Validation = { + + validate: function(property, value){ + + //normalize name + var name = property.toString().toLowerCase(), + valid, + spec = Properties[name], + i, len, j, count, + msg, + types, + last, + max, multi, + parts = value.parts; + + if (!spec) { + if (name.indexOf("-") !== 0){ //vendor prefixed are ok + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); + } + } else if (typeof spec != "number"){ + + //initialization + if (spec instanceof Array){ + types = spec; + max = 1; + } else if (spec.multi) { + types = spec.multi; + max = spec.max; + } + + //Start validation---- + + //if there's a maximum set, use it (max can't be 0) + if (max) { + if (parts.length > max){ + throw new ValidationError("Expected a max of " + max + " property value(s) but found " + parts.length + ".", value.line, value.col); + } + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(types); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); + } else { + valid = true; + } + } else { + + for (j=0, count=types.length; j < count; j++){ + if (typeof Validation.types[types[j]] == "undefined"){ + if(Validation.types.identifier(parts[i], types[j])){ + valid = true; + break; + } + msg.push("one of (" + types[j] + ")"); + } else { + if (Validation.types[types[j]](parts[i])){ + valid = true; + break; + } + msg.push(types[j]); + } + } + } + + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + + + last = parts[i]; + } + + + + } + }, + + types: { + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return this.length(part) || this.identifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } + } + +}; /** * Type to use when a validation error occurs. * @class ValidationError diff --git a/lib/yuitest.js b/lib/yuitest.js new file mode 100644 index 00000000..4a6c8325 --- /dev/null +++ b/lib/yuitest.js @@ -0,0 +1,4561 @@ +/** + * YUI Test Framework + * @module yuitest + */ + +/** + * The root namespace for YUI Test. + * @class YUITest + * @static + */ + +var YUITest = { + version: "@VERSION@" +}; + + +/** + * Simple custom event implementation. + * @namespace YUITest + * @class EventTarget + * @constructor + */ +YUITest.EventTarget = function(){ + + /** + * Event handlers for the various events. + * @type Object + * @private + * @property _handlers + * @static + */ + this._handlers = {}; + +}; + +YUITest.EventTarget.prototype = { + + //restore prototype + constructor: YUITest.EventTarget, + + //------------------------------------------------------------------------- + // Event Handling + //------------------------------------------------------------------------- + + /** + * Adds a listener for a given event type. + * @param {String} type The type of event to add a listener for. + * @param {Function} listener The function to call when the event occurs. + * @return {void} + * @method attach + */ + attach: function(type, listener){ + if (typeof this._handlers[type] == "undefined"){ + this._handlers[type] = []; + } + + this._handlers[type].push(listener); + }, + + /** + * Adds a listener for a given event type. + * @param {String} type The type of event to add a listener for. + * @param {Function} listener The function to call when the event occurs. + * @return {void} + * @method subscribe + * @deprecated + */ + subscribe: function(type, listener){ + this.attach.apply(this, arguments); + }, + + /** + * Fires an event based on the passed-in object. + * @param {Object|String} event An object with at least a 'type' attribute + * or a string indicating the event name. + * @return {void} + * @method fire + */ + fire: function(event){ + if (typeof event == "string"){ + event = { type: event }; + } + if (!event.target){ + event.target = this; + } + + if (!event.type){ + throw new Error("Event object missing 'type' property."); + } + + if (this._handlers[event.type] instanceof Array){ + var handlers = this._handlers[event.type]; + for (var i=0, len=handlers.length; i < len; i++){ + handlers[i].call(this, event); + } + } + }, + + /** + * Removes a listener for a given event type. + * @param {String} type The type of event to remove a listener from. + * @param {Function} listener The function to remove from the event. + * @return {void} + * @method detach + */ + detach: function(type, listener){ + if (this._handlers[type] instanceof Array){ + var handlers = this._handlers[type]; + for (var i=0, len=handlers.length; i < len; i++){ + if (handlers[i] === listener){ + handlers.splice(i, 1); + break; + } + } + } + }, + + /** + * Removes a listener for a given event type. + * @param {String} type The type of event to remove a listener from. + * @param {Function} listener The function to remove from the event. + * @return {void} + * @method unsubscribe + * @deprecated + */ + unsubscribe: function(type, listener){ + this.detach.apply(this, arguments); + } + +}; + + +/** + * Object containing helper methods. + * @namespace YUITest + * @class Util + * @static + */ +YUITest.Util = { + + /** + * Mixes the own properties from the supplier onto the + * receiver. + * @param {Object} receiver The object to receive the properties. + * @param {Object} supplier The object to supply the properties. + * @return {Object} The receiver that was passed in. + * @method mix + * @static + */ + mix: function(receiver, supplier){ + + for (var prop in supplier){ + if (supplier.hasOwnProperty(prop)){ + receiver[prop] = supplier[prop]; + } + } + + return receiver; + }, + + /** + * Stub for JSON functionality. When the native JSON utility + * is available, it will be used. Otherwise, a stub object + * is created. Developers should override YUITest.Util.JSON + * when attempting to use it in environments where a native + * JSON utility is unavailable. + * @property JSON + * @type JSON + * @static + */ + JSON: typeof JSON != "undefined" ? JSON : { + stringify: function(){ + //TODO: Should include code to do this? + throw new Error("No JSON utility specified."); + } + } + +}; + + +/** + * Error is thrown whenever an assertion fails. It provides methods + * to more easily get at error information and also provides a base class + * from which more specific assertion errors can be derived. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @class AssertionError + * @constructor + */ +YUITest.AssertionError = function (message){ + + /** + * Error message. Must be duplicated to ensure browser receives it. + * @type String + * @property message + */ + this.message = message; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "Assert Error"; +}; + +YUITest.AssertionError.prototype = { + + //restore constructor + constructor: YUITest.AssertionError, + + /** + * Returns a fully formatted error for an assertion failure. This should + * be overridden by all subclasses to provide specific information. + * @method getMessage + * @return {String} A string describing the error. + */ + getMessage : function () { + return this.message; + }, + + /** + * Returns a string representation of the error. + * @method toString + * @return {String} A string representation of the error. + */ + toString : function () { + return this.name + ": " + this.getMessage(); + } + +}; + +/** + * ComparisonFailure is subclass of Error that is thrown whenever + * a comparison between two values fails. It provides mechanisms to retrieve + * both the expected and actual value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value that caused the assertion to fail. + * @namespace YUITest + * @extends AssertionError + * @class ComparisonFailure + * @constructor + */ +YUITest.ComparisonFailure = function (message, expected, actual){ + + //call superclass + YUITest.AssertionError.call(this, message); + + /** + * The expected value. + * @type Object + * @property expected + */ + this.expected = expected; + + /** + * The actual value. + * @type Object + * @property actual + */ + this.actual = actual; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ComparisonFailure"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ComparisonFailure.prototype = new YUITest.AssertionError; + +//restore constructor +YUITest.ComparisonFailure.prototype.constructor = YUITest.ComparisonFailure; + +/** + * Returns a fully formatted error for an assertion failure. This message + * provides information about the expected and actual values. + * @method getMessage + * @return {String} A string describing the error. + */ +YUITest.ComparisonFailure.prototype.getMessage = function(){ + return this.message + "\nExpected: " + this.expected + " (" + (typeof this.expected) + ")" + + "\nActual: " + this.actual + " (" + (typeof this.actual) + ")"; +}; + +/** + * ShouldError is subclass of Error that is thrown whenever + * a test is expected to throw an error but doesn't. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @extends AssertionError + * @class ShouldError + * @constructor + */ +YUITest.ShouldError = function (message){ + + //call superclass + YUITest.AssertionError.call(this, message || "This test should have thrown an error but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ShouldError"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ShouldError.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.ShouldError.prototype.constructor = YUITest.ShouldError; + +/** + * ShouldFail is subclass of AssertionError that is thrown whenever + * a test was expected to fail but did not. + * + * @param {String} message The message to display when the error occurs. + * @namespace YUITest + * @extends YUITest.AssertionError + * @class ShouldFail + * @constructor + */ +YUITest.ShouldFail = function (message){ + + //call superclass + YUITest.AssertionError.call(this, message || "This test should fail but didn't."); + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "ShouldFail"; + +}; + +//inherit from YUITest.AssertionError +YUITest.ShouldFail.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.ShouldFail.prototype.constructor = YUITest.ShouldFail; + +/** + * UnexpectedError is subclass of AssertionError that is thrown whenever + * an error occurs within the course of a test and the test was not expected + * to throw an error. + * + * @param {Error} cause The unexpected error that caused this error to be + * thrown. + * @namespace YUITest + * @extends YUITest.AssertionError + * @class UnexpectedError + * @constructor + */ +YUITest.UnexpectedError = function (cause){ + + //call superclass + YUITest.AssertionError.call(this, "Unexpected error: " + cause.message); + + /** + * The unexpected error that occurred. + * @type Error + * @property cause + */ + this.cause = cause; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "UnexpectedError"; + + /** + * Stack information for the error (if provided). + * @type String + * @property stack + */ + this.stack = cause.stack; + +}; + +//inherit from YUITest.AssertionError +YUITest.UnexpectedError.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.UnexpectedError.prototype.constructor = YUITest.UnexpectedError; + +/** + * UnexpectedValue is subclass of Error that is thrown whenever + * a value was unexpected in its scope. This typically means that a test + * was performed to determine that a value was *not* equal to a certain + * value. + * + * @param {String} message The message to display when the error occurs. + * @param {Object} unexpected The unexpected value. + * @namespace YUITest + * @extends AssertionError + * @class UnexpectedValue + * @constructor + */ +YUITest.UnexpectedValue = function (message, unexpected){ + + //call superclass + YUITest.AssertionError.call(this, message); + + /** + * The unexpected value. + * @type Object + * @property unexpected + */ + this.unexpected = unexpected; + + /** + * The name of the error that occurred. + * @type String + * @property name + */ + this.name = "UnexpectedValue"; + +}; + +//inherit from YUITest.AssertionError +YUITest.UnexpectedValue.prototype = new YUITest.AssertionError(); + +//restore constructor +YUITest.UnexpectedValue.prototype.constructor = YUITest.UnexpectedValue; + +/** + * Returns a fully formatted error for an assertion failure. This message + * provides information about the expected and actual values. + * @method getMessage + * @return {String} A string describing the error. + */ +YUITest.UnexpectedValue.prototype.getMessage = function(){ + return this.message + "\nUnexpected: " + this.unexpected + " (" + (typeof this.unexpected) + ") "; +}; + + +/** + * Represents a stoppage in test execution to wait for an amount of time before + * continuing. + * @param {Function} segment A function to run when the wait is over. + * @param {int} delay The number of milliseconds to wait before running the code. + * @class Wait + * @namespace Test + * @constructor + * + */ +YUITest.Wait = function (segment, delay) { + + /** + * The segment of code to run when the wait is over. + * @type Function + * @property segment + */ + this.segment = (typeof segment == "function" ? segment : null); + + /** + * The delay before running the segment of code. + * @type int + * @property delay + */ + this.delay = (typeof delay == "number" ? delay : 0); +}; + + +/** + * The Assert object provides functions to test JavaScript values against + * known and expected results. Whenever a comparison (assertion) fails, + * an error is thrown. + * @namespace YUITest + * @class Assert + * @static + */ +YUITest.Assert = { + + /** + * The number of assertions performed. + * @property _asserts + * @type int + * @private + */ + _asserts: 0, + + //------------------------------------------------------------------------- + // Helper Methods + //------------------------------------------------------------------------- + + /** + * Formats a message so that it can contain the original assertion message + * in addition to the custom message. + * @param {String} customMessage The message passed in by the developer. + * @param {String} defaultMessage The message created by the error by default. + * @return {String} The final error message, containing either or both. + * @protected + * @static + * @method _formatMessage + */ + _formatMessage : function (customMessage, defaultMessage) { + if (typeof customMessage == "string" && customMessage.length > 0){ + return customMessage.replace("{message}", defaultMessage); + } else { + return defaultMessage; + } + }, + + /** + * Returns the number of assertions that have been performed. + * @method _getCount + * @protected + * @static + */ + _getCount: function(){ + return this._asserts; + }, + + /** + * Increments the number of assertions that have been performed. + * @method _increment + * @protected + * @static + */ + _increment: function(){ + this._asserts++; + }, + + /** + * Resets the number of assertions that have been performed to 0. + * @method _reset + * @protected + * @static + */ + _reset: function(){ + this._asserts = 0; + }, + + //------------------------------------------------------------------------- + // Generic Assertion Methods + //------------------------------------------------------------------------- + + /** + * Forces an assertion error to occur. + * @param {String} message (Optional) The message to display with the failure. + * @method fail + * @static + */ + fail : function (message) { + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Test force-failed.")); + }, + + //------------------------------------------------------------------------- + // Equality Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is equal to another. This uses the double equals sign + * so type cohersion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areEqual + * @static + */ + areEqual : function (expected, actual, message) { + YUITest.Assert._increment(); + if (expected != actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be equal."), expected, actual); + } + }, + + /** + * Asserts that a value is not equal to another. This uses the double equals sign + * so type cohersion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotEqual + * @static + */ + areNotEqual : function (unexpected, actual, + message) { + YUITest.Assert._increment(); + if (unexpected == actual) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be equal."), unexpected); + } + }, + + /** + * Asserts that a value is not the same as another. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} unexpected The unexpected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areNotSame + * @static + */ + areNotSame : function (unexpected, actual, message) { + YUITest.Assert._increment(); + if (unexpected === actual) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be the same."), unexpected); + } + }, + + /** + * Asserts that a value is the same as another. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} expected The expected value. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areSame + * @static + */ + areSame : function (expected, actual, message) { + YUITest.Assert._increment(); + if (expected !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be the same."), expected, actual); + } + }, + + //------------------------------------------------------------------------- + // Boolean Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is false. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFalse + * @static + */ + isFalse : function (actual, message) { + YUITest.Assert._increment(); + if (false !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be false."), false, actual); + } + }, + + /** + * Asserts that a value is true. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTrue + * @static + */ + isTrue : function (actual, message) { + YUITest.Assert._increment(); + if (true !== actual) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be true."), true, actual); + } + + }, + + //------------------------------------------------------------------------- + // Special Value Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a value is not a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNaN + * @static + */ + isNaN : function (actual, message){ + YUITest.Assert._increment(); + if (!isNaN(actual)){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be NaN."), NaN, actual); + } + }, + + /** + * Asserts that a value is not the special NaN value. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNaN + * @static + */ + isNotNaN : function (actual, message){ + YUITest.Assert._increment(); + if (isNaN(actual)){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be NaN."), NaN); + } + }, + + /** + * Asserts that a value is not null. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotNull + * @static + */ + isNotNull : function (actual, message) { + YUITest.Assert._increment(); + if (actual === null) { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Values should not be null."), null); + } + }, + + /** + * Asserts that a value is not undefined. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotUndefined + * @static + */ + isNotUndefined : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual == "undefined") { + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should not be undefined."), undefined); + } + }, + + /** + * Asserts that a value is null. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNull + * @static + */ + isNull : function (actual, message) { + YUITest.Assert._increment(); + if (actual !== null) { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be null."), null, actual); + } + }, + + /** + * Asserts that a value is undefined. This uses the triple equals sign + * so no type cohersion may occur. + * @param {Object} actual The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isUndefined + * @static + */ + isUndefined : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "undefined") { + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be undefined."), undefined, actual); + } + }, + + //-------------------------------------------------------------------------- + // Instance Assertion Methods + //-------------------------------------------------------------------------- + + /** + * Asserts that a value is an array. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isArray + * @static + */ + isArray : function (actual, message) { + YUITest.Assert._increment(); + var shouldFail = false; + if (Array.isArray){ + shouldFail = !Array.isArray(actual); + } else { + shouldFail = Object.prototype.toString.call(actual) != "[object Array]"; + } + if (shouldFail){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be an array."), actual); + } + }, + + /** + * Asserts that a value is a Boolean. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isBoolean + * @static + */ + isBoolean : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "boolean"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a Boolean."), actual); + } + }, + + /** + * Asserts that a value is a function. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isFunction + * @static + */ + isFunction : function (actual, message) { + YUITest.Assert._increment(); + if (!(actual instanceof Function)){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a function."), actual); + } + }, + + /** + * Asserts that a value is an instance of a particular object. This may return + * incorrect results when comparing objects from one frame to constructors in + * another frame. For best results, don't use in a cross-frame manner. + * @param {Function} expected The function that the object should be an instance of. + * @param {Object} actual The object to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isInstanceOf + * @static + */ + isInstanceOf : function (expected, actual, message) { + YUITest.Assert._increment(); + if (!(actual instanceof expected)){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value isn't an instance of expected type."), expected, actual); + } + }, + + /** + * Asserts that a value is a number. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNumber + * @static + */ + isNumber : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "number"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a number."), actual); + } + }, + + /** + * Asserts that a value is an object. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isObject + * @static + */ + isObject : function (actual, message) { + YUITest.Assert._increment(); + if (!actual || (typeof actual != "object" && typeof actual != "function")){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be an object."), actual); + } + }, + + /** + * Asserts that a value is a string. + * @param {Object} actual The value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isString + * @static + */ + isString : function (actual, message) { + YUITest.Assert._increment(); + if (typeof actual != "string"){ + throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, "Value should be a string."), actual); + } + }, + + /** + * Asserts that a value is of a particular type. + * @param {String} expectedType The expected type of the variable. + * @param {Object} actualValue The actual value to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isTypeOf + * @static + */ + isTypeOf : function (expectedType, actualValue, message){ + YUITest.Assert._increment(); + if (typeof actualValue != expectedType){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Value should be of type " + expectedType + "."), expectedType, typeof actualValue); + } + }, + + //-------------------------------------------------------------------------- + // Error Detection Methods + //-------------------------------------------------------------------------- + + /** + * Asserts that executing a particular method should throw an error of + * a specific type. This is a replacement for _should.error. + * @param {String|Function|Object} expectedError If a string, this + * is the error message that the error must have; if a function, this + * is the constructor that should have been used to create the thrown + * error; if an object, this is an instance of a particular error type + * with a specific error message (both must match). + * @param {Function} method The method to execute that should throw the error. + * @param {String} message (Optional) The message to display if the assertion + * fails. + * @method throwsError + * @return {void} + * @static + */ + throwsError: function(expectedError, method, message){ + YUITest.Assert._increment(); + var error = false; + + try { + method(); + } catch (thrown) { + + //check to see what type of data we have + if (typeof expectedError == "string"){ + + //if it's a string, check the error message + if (thrown.message != expectedError){ + error = true; + } + } else if (typeof expectedError == "function"){ + + //if it's a function, see if the error is an instance of it + if (!(thrown instanceof expectedError)){ + error = true; + } + + } else if (typeof expectedError == "object" && expectedError !== null){ + + //if it's an object, check the instance and message + if (!(thrown instanceof expectedError.constructor) || + thrown.message != expectedError.message){ + error = true; + } + + } else { //if it gets here, the argument could be wrong + error = true; + } + + if (error){ + throw new YUITest.UnexpectedError(thrown); + } else { + return; + } + } + + //if it reaches here, the error wasn't thrown, which is a bad thing + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Error should have been thrown.")); + } + +}; + + +/** + * The ArrayAssert object provides functions to test JavaScript array objects + * for a variety of cases. + * @namespace YUITest + * @class ArrayAssert + * @static + */ + +YUITest.ArrayAssert = { + + //========================================================================= + // Private methods + //========================================================================= + + /** + * Simple indexOf() implementation for an array. Defers to native + * if available. + * @param {Array} haystack The array to search. + * @param {Variant} needle The value to locate. + * @return {int} The index of the needle if found or -1 if not. + * @method _indexOf + * @private + */ + _indexOf: function(haystack, needle){ + if (haystack.indexOf){ + return haystack.indexOf(needle); + } else { + for (var i=0; i < haystack.length; i++){ + if (haystack[i] === needle){ + return i; + } + } + return -1; + } + }, + + /** + * Simple some() implementation for an array. Defers to native + * if available. + * @param {Array} haystack The array to search. + * @param {Function} matcher The function to run on each value. + * @return {Boolean} True if any value, when run through the matcher, + * returns true. + * @method _some + * @private + */ + _some: function(haystack, matcher){ + if (haystack.some){ + return haystack.some(matcher); + } else { + for (var i=0; i < haystack.length; i++){ + if (matcher(haystack[i])){ + return true; + } + } + return false; + } + }, + + /** + * Asserts that a value is present in an array. This uses the triple equals + * sign so no type cohersion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method contains + * @static + */ + contains : function (needle, haystack, + message) { + + YUITest.Assert._increment(); + + if (this._indexOf(haystack, needle) == -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value " + needle + " (" + (typeof needle) + ") not found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are present in an array. This uses the triple equals + * sign so no type cohersion may occur. For this assertion to pass, all values must + * be found. + * @param {Object[]} needles An array of values that are expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsItems + * @static + */ + containsItems : function (needles, haystack, + message) { + YUITest.Assert._increment(); + + //begin checking values + for (var i=0; i < needles.length; i++){ + if (this._indexOf(haystack, needles[i]) == -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value " + needles[i] + " (" + (typeof needles[i]) + ") not found in array [" + haystack + "].")); + } + } + }, + + /** + * Asserts that a value matching some condition is present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the items matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method containsMatch + * @static + */ + containsMatch : function (matcher, haystack, + message) { + + YUITest.Assert._increment(); + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.containsMatch(): First argument must be a function."); + } + + if (!this._some(haystack, matcher)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "No match found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a value is not present in an array. This uses the triple equals + * Asserts that a value is not present in an array. This uses the triple equals + * sign so no type cohersion may occur. + * @param {Object} needle The value that is expected in the array. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContain + * @static + */ + doesNotContain : function (needle, haystack, + message) { + + YUITest.Assert._increment(); + + if (this._indexOf(haystack, needle) > -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that a set of values are not present in an array. This uses the triple equals + * sign so no type cohersion may occur. For this assertion to pass, all values must + * not be found. + * @param {Object[]} needles An array of values that are not expected in the array. + * @param {Array} haystack An array of values to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainItems + * @static + */ + doesNotContainItems : function (needles, haystack, + message) { + + YUITest.Assert._increment(); + + for (var i=0; i < needles.length; i++){ + if (this._indexOf(haystack, needles[i]) > -1){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + } + + }, + + /** + * Asserts that no values matching a condition are present in an array. This uses + * a function to determine a match. + * @param {Function} matcher A function that returns true if the item matches or false if not. + * @param {Array} haystack An array of values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method doesNotContainMatch + * @static + */ + doesNotContainMatch : function (matcher, haystack, + message) { + + YUITest.Assert._increment(); + + //check for valid matcher + if (typeof matcher != "function"){ + throw new TypeError("ArrayAssert.doesNotContainMatch(): First argument must be a function."); + } + + if (this._some(haystack, matcher)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value found in array [" + haystack + "].")); + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index. + * This uses the triple equals sign so no type cohersion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method indexOf + * @static + */ + indexOf : function (needle, haystack, index, message) { + + YUITest.Assert._increment(); + + //try to find the value in the array + for (var i=0; i < haystack.length; i++){ + if (haystack[i] === needle){ + if (index != i){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); + } + return; + } + } + + //if it makes it here, it wasn't found at all + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value doesn't exist in array [" + haystack + "].")); + }, + + /** + * Asserts that the values in an array are equal, and in the same position, + * as values in another array. This uses the double equals sign + * so type cohersion may occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreEqual + * @static + */ + itemsAreEqual : function (expected, actual, + message) { + + YUITest.Assert._increment(); + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (expected[i] != actual[i]){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not equal."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that the values in an array are equivalent, and in the same position, + * as values in another array. This uses a function to determine if the values + * are equivalent. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {Function} comparator A function that returns true if the values are equivalent + * or false if not. + * @param {String} message (Optional) The message to display if the assertion fails. + * @return {Void} + * @method itemsAreEquivalent + * @static + */ + itemsAreEquivalent : function (expected, actual, + comparator, message) { + + YUITest.Assert._increment(); + + //make sure the comparator is valid + if (typeof comparator != "function"){ + throw new TypeError("ArrayAssert.itemsAreEquivalent(): Third argument must be a function."); + } + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (!comparator(expected[i], actual[i])){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not equivalent."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that an array is empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isEmpty + * @static + */ + isEmpty : function (actual, message) { + YUITest.Assert._increment(); + if (actual.length > 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should be empty.")); + } + }, + + /** + * Asserts that an array is not empty. + * @param {Array} actual The array to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method isNotEmpty + * @static + */ + isNotEmpty : function (actual, message) { + YUITest.Assert._increment(); + if (actual.length === 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should not be empty.")); + } + }, + + /** + * Asserts that the values in an array are the same, and in the same position, + * as values in another array. This uses the triple equals sign + * so no type cohersion will occur. Note that the array objects themselves + * need not be the same for this test to pass. + * @param {Array} expected An array of the expected values. + * @param {Array} actual Any array of the actual values. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method itemsAreSame + * @static + */ + itemsAreSame : function (expected, actual, + message) { + + YUITest.Assert._increment(); + + //first check array length + if (expected.length != actual.length){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Array should have a length of " + expected.length + " but has a length of " + actual.length)); + } + + //begin checking values + for (var i=0; i < expected.length; i++){ + if (expected[i] !== actual[i]){ + throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values in position " + i + " are not the same."), expected[i], actual[i]); + } + } + }, + + /** + * Asserts that the given value is contained in an array at the specified index, + * starting from the back of the array. + * This uses the triple equals sign so no type cohersion will occur. + * @param {Object} needle The value to look for. + * @param {Array} haystack The array to search in. + * @param {int} index The index at which the value should exist. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method lastIndexOf + * @static + */ + lastIndexOf : function (needle, haystack, index, message) { + + //try to find the value in the array + for (var i=haystack.length; i >= 0; i--){ + if (haystack[i] === needle){ + if (index != i){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value exists at index " + i + " but should be at index " + index + ".")); + } + return; + } + } + + //if it makes it here, it wasn't found at all + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Value doesn't exist in array.")); + } + +}; + + +/** + * The ObjectAssert object provides functions to test JavaScript objects + * for a variety of cases. + * @namespace YUITest + * @class ObjectAssert + * @static + */ +YUITest.ObjectAssert = { + + /** + * Asserts that an object has all of the same properties + * and property values as the other. + * @param {Object} expected The object with all expected properties and values. + * @param {Object} actual The object to inspect. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method areEqual + * @static + * @deprecated + */ + areEqual: function(expected, actual, message) { + YUITest.Assert._increment(); + + for (var name in expected){ + if (expected.hasOwnProperty(name)){ + if (expected[name] != actual[name]){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, "Values should be equal for property " + name), expected[name], actual[name]); + } + } + } + }, + + /** + * Asserts that an object has a property with the given name. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasKey + * @static + * @deprecated Use ownsOrInheritsKey() instead + */ + hasKey: function (propertyName, object, message) { + YUITest.ObjectAssert.ownsOrInheritsKey(propertyName, object, message); + }, + + /** + * Asserts that an object has all properties of a reference object. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method hasKeys + * @static + * @deprecated Use ownsOrInheritsKeys() instead + */ + hasKeys: function (properties, object, message) { + YUITest.ObjectAssert.ownsOrInheritsKeys(properties, objects, message); + }, + + /** + * Asserts that a property with the given name exists on an object's prototype. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method inheritsKey + * @static + */ + inheritsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!(propertyName in object && !object.hasOwnProperty(propertyName))){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); + } + }, + + /** + * Asserts that all properties exist on an object prototype. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method inheritsKeys + * @static + */ + inheritsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!(propertyName in object && !object.hasOwnProperty(properties[i]))){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object instance.")); + } + } + }, + + /** + * Asserts that a property with the given name exists on an object instance (not on its prototype). + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsKey + * @static + */ + ownsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!object.hasOwnProperty(propertyName)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object instance.")); + } + }, + + /** + * Asserts that all properties exist on an object instance (not on its prototype). + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsKeys + * @static + */ + ownsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!object.hasOwnProperty(properties[i])){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object instance.")); + } + } + }, + + /** + * Asserts that an object owns no properties. + * @param {Object} object The object to check. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsNoKeys + * @static + */ + ownsNoKeys : function (object, message) { + YUITest.Assert._increment(); + var count = 0, + name; + for (name in object){ + if (object.hasOwnProperty(name)){ + count++; + } + } + + if (count !== 0){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Object owns " + count + " properties but should own none.")); + } + + }, + + /** + * Asserts that an object has a property with the given name. + * @param {String} propertyName The name of the property to test. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsOrInheritsKey + * @static + */ + ownsOrInheritsKey: function (propertyName, object, message) { + YUITest.Assert._increment(); + if (!(propertyName in object)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + propertyName + "' not found on object.")); + } + }, + + /** + * Asserts that an object has all properties of a reference object. + * @param {Array} properties An array of property names that should be on the object. + * @param {Object} object The object to search. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method ownsOrInheritsKeys + * @static + */ + ownsOrInheritsKeys: function (properties, object, message) { + YUITest.Assert._increment(); + for (var i=0; i < properties.length; i++){ + if (!(properties[i] in object)){ + YUITest.Assert.fail(YUITest.Assert._formatMessage(message, "Property '" + properties[i] + "' not found on object.")); + } + } + } +}; + + + +/** + * The DateAssert object provides functions to test JavaScript Date objects + * for a variety of cases. + * @namespace YUITest + * @class DateAssert + * @static + */ + +YUITest.DateAssert = { + + /** + * Asserts that a date's month, day, and year are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method datesAreEqual + * @static + */ + datesAreEqual : function (expected, actual, message){ + YUITest.Assert._increment(); + if (expected instanceof Date && actual instanceof Date){ + var msg = ""; + + //check years first + if (expected.getFullYear() != actual.getFullYear()){ + msg = "Years should be equal."; + } + + //now check months + if (expected.getMonth() != actual.getMonth()){ + msg = "Months should be equal."; + } + + //last, check the day of the month + if (expected.getDate() != actual.getDate()){ + msg = "Days of month should be equal."; + } + + if (msg.length){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual); + } + } else { + throw new TypeError("YUITest.DateAssert.datesAreEqual(): Expected and actual values must be Date objects."); + } + }, + + /** + * Asserts that a date's hour, minutes, and seconds are equal to another date's. + * @param {Date} expected The expected date. + * @param {Date} actual The actual date to test. + * @param {String} message (Optional) The message to display if the assertion fails. + * @method timesAreEqual + * @static + */ + timesAreEqual : function (expected, actual, message){ + YUITest.Assert._increment(); + if (expected instanceof Date && actual instanceof Date){ + var msg = ""; + + //check hours first + if (expected.getHours() != actual.getHours()){ + msg = "Hours should be equal."; + } + + //now check minutes + if (expected.getMinutes() != actual.getMinutes()){ + msg = "Minutes should be equal."; + } + + //last, check the seconds + if (expected.getSeconds() != actual.getSeconds()){ + msg = "Seconds should be equal."; + } + + if (msg.length){ + throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual); + } + } else { + throw new TypeError("YUITest.DateAssert.timesAreEqual(): Expected and actual values must be Date objects."); + } + } + +}; + +/** + * Creates a new mock object. + * @namespace YUITest + * @class Mock + * @constructor + * @param {Object} template (Optional) An object whose methods + * should be stubbed out on the mock object. + */ +YUITest.Mock = function(template){ + + //use blank object is nothing is passed in + template = template || {}; + + var mock, + name; + + //try to create mock that keeps prototype chain intact + //fails in the case of ActiveX objects + try { + function f(){} + f.prototype = template; + mock = new f(); + } catch (ex) { + mock = {}; + } + + //create stubs for all methods + for (name in template){ + if (template.hasOwnProperty(name)){ + if (typeof template[name] == "function"){ + mock[name] = function(name){ + return function(){ + YUITest.Assert.fail("Method " + name + "() was called but was not expected to be."); + }; + }(name); + } + } + } + + //return it + return mock; +}; + +/** + * Assigns an expectation to a mock object. This is used to create + * methods and properties on the mock object that are monitored for + * calls and changes, respectively. + * @param {Object} mock The object to add the expectation to. + * @param {Object} expectation An object defining the expectation. For + * a method, the keys "method" and "args" are required with + * an optional "returns" key available. For properties, the keys + * "property" and "value" are required. + * @return {void} + * @method expect + * @static + */ +YUITest.Mock.expect = function(mock /*:Object*/, expectation /*:Object*/){ + + //make sure there's a place to store the expectations + if (!mock.__expectations) { + mock.__expectations = {}; + } + + //method expectation + if (expectation.method){ + var name = expectation.method, + args = expectation.args || [], + result = expectation.returns, + callCount = (typeof expectation.callCount == "number") ? expectation.callCount : 1, + error = expectation.error, + run = expectation.run || function(){}, + i; + + //save expectations + mock.__expectations[name] = expectation; + expectation.callCount = callCount; + expectation.actualCallCount = 0; + + //process arguments + for (i=0; i < args.length; i++){ + if (!(args[i] instanceof YUITest.Mock.Value)){ + args[i] = YUITest.Mock.Value(YUITest.Assert.areSame, [args[i]], "Argument " + i + " of " + name + "() is incorrect."); + } + } + + //if the method is expected to be called + if (callCount > 0){ + mock[name] = function(){ + try { + expectation.actualCallCount++; + YUITest.Assert.areEqual(args.length, arguments.length, "Method " + name + "() passed incorrect number of arguments."); + for (var i=0, len=args.length; i < len; i++){ + args[i].verify(arguments[i]); + } + + run.apply(this, arguments); + + if (error){ + throw error; + } + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } + + return result; + }; + } else { + + //method should fail if called when not expected + mock[name] = function(){ + try { + YUITest.Assert.fail("Method " + name + "() should not have been called."); + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } + }; + } + } else if (expectation.property){ + //save expectations + mock.__expectations[name] = expectation; + } +}; + +/** + * Verifies that all expectations of a mock object have been met and + * throws an assertion error if not. + * @param {Object} mock The object to verify.. + * @return {void} + * @method verify + * @static + */ +YUITest.Mock.verify = function(mock){ + try { + + for (var name in mock.__expectations){ + if (mock.__expectations.hasOwnProperty(name)){ + var expectation = mock.__expectations[name]; + if (expectation.method) { + YUITest.Assert.areEqual(expectation.callCount, expectation.actualCallCount, "Method " + expectation.method + "() wasn't called the expected number of times."); + } else if (expectation.property){ + YUITest.Assert.areEqual(expectation.value, mock[expectation.property], "Property " + expectation.property + " wasn't set to the correct value."); + } + } + } + + } catch (ex){ + //route through TestRunner for proper handling + YUITest.TestRunner._handleError(ex); + } +}; + +/** + * Creates a new value matcher. + * @param {Function} method The function to call on the value. + * @param {Array} originalArgs (Optional) Array of arguments to pass to the method. + * @param {String} message (Optional) Message to display in case of failure. + * @namespace YUITest.Mock + * @class Value + * @constructor + */ +YUITest.Mock.Value = function(method, originalArgs, message){ + if (this instanceof YUITest.Mock.Value){ + this.verify = function(value){ + var args = [].concat(originalArgs || []); + args.push(value); + args.push(message); + method.apply(null, args); + }; + } else { + return new YUITest.Mock.Value(method, originalArgs, message); + } +}; + +/** + * Predefined matcher to match any value. + * @property Any + * @static + * @type Function + */ +YUITest.Mock.Value.Any = YUITest.Mock.Value(function(){}); + +/** + * Predefined matcher to match boolean values. + * @property Boolean + * @static + * @type Function + */ +YUITest.Mock.Value.Boolean = YUITest.Mock.Value(YUITest.Assert.isBoolean); + +/** + * Predefined matcher to match number values. + * @property Number + * @static + * @type Function + */ +YUITest.Mock.Value.Number = YUITest.Mock.Value(YUITest.Assert.isNumber); + +/** + * Predefined matcher to match string values. + * @property String + * @static + * @type Function + */ +YUITest.Mock.Value.String = YUITest.Mock.Value(YUITest.Assert.isString); + +/** + * Predefined matcher to match object values. + * @property Object + * @static + * @type Function + */ +YUITest.Mock.Value.Object = YUITest.Mock.Value(YUITest.Assert.isObject); + +/** + * Predefined matcher to match function values. + * @property Function + * @static + * @type Function + */ +YUITest.Mock.Value.Function = YUITest.Mock.Value(YUITest.Assert.isFunction); + +/** + * Convenience type for storing and aggregating + * test result information. + * @private + * @namespace YUITest + * @class Results + * @constructor + * @param {String} name The name of the test. + */ +YUITest.Results = function(name){ + + /** + * Name of the test, test case, or test suite. + * @type String + * @property name + */ + this.name = name; + + /** + * Number of passed tests. + * @type int + * @property passed + */ + this.passed = 0; + + /** + * Number of failed tests. + * @type int + * @property failed + */ + this.failed = 0; + + /** + * Number of errors that occur in non-test methods. + * @type int + * @property errors + */ + this.errors = 0; + + /** + * Number of ignored tests. + * @type int + * @property ignored + */ + this.ignored = 0; + + /** + * Number of total tests. + * @type int + * @property total + */ + this.total = 0; + + /** + * Amount of time (ms) it took to complete testing. + * @type int + * @property duration + */ + this.duration = 0; +}; + +/** + * Includes results from another results object into this one. + * @param {YUITest.Results} result The results object to include. + * @method include + * @return {void} + */ +YUITest.Results.prototype.include = function(results){ + this.passed += results.passed; + this.failed += results.failed; + this.ignored += results.ignored; + this.total += results.total; + this.errors += results.errors; +}; + +/** + * Test case containing various tests to run. + * @param template An object containing any number of test methods, other methods, + * an optional name, and anything else the test case needs. + * @class TestCase + * @namespace YUITest + * @constructor + */ +YUITest.TestCase = function (template) { + + /** + * Special rules for the test case. Possible subobjects + * are fail, for tests that should fail, and error, for + * tests that should throw an error. + */ + this._should = {}; + + //copy over all properties from the template to this object + for (var prop in template) { + this[prop] = template[prop]; + } + + //check for a valid name + if (typeof this.name != "string"){ + this.name = "testCase" + (+new Date()); + } + +}; + +YUITest.TestCase.prototype = { + + //restore constructor + constructor: YUITest.TestCase, + + /** + * Method to call from an async init method to + * restart the test case. When called, returns a function + * that should be called when tests are ready to continue. + * @method callback + * @return {Function} The function to call as a callback. + */ + callback: function(){ + return YUITest.TestRunner.callback.apply(YUITest.TestRunner,arguments); + }, + + /** + * Resumes a paused test and runs the given function. + * @param {Function} segment (Optional) The function to run. + * If omitted, the test automatically passes. + * @return {Void} + * @method resume + */ + resume : function (segment) { + YUITest.TestRunner.resume(segment); + }, + + /** + * Causes the test case to wait a specified amount of time and then + * continue executing the given code. + * @param {Function} segment (Optional) The function to run after the delay. + * If omitted, the TestRunner will wait until resume() is called. + * @param {int} delay (Optional) The number of milliseconds to wait before running + * the function. If omitted, defaults to zero. + * @return {Void} + * @method wait + */ + wait : function (segment, delay){ + + var actualDelay = (typeof segment == "number" ? segment : delay); + actualDelay = (typeof actualDelay == "number" ? actualDelay : 10000); + + if (typeof segment == "function"){ + throw new YUITest.Wait(segment, actualDelay); + } else { + throw new YUITest.Wait(function(){ + YUITest.Assert.fail("Timeout: wait() called but resume() never called."); + }, actualDelay); + } + }, + + //------------------------------------------------------------------------- + // Assertion Methods + //------------------------------------------------------------------------- + + /** + * Asserts that a given condition is true. If not, then a YUITest.AssertionError object is thrown + * and the test fails. + * @method assert + * @param {Boolean} condition The condition to test. + * @param {String} message The message to display if the assertion fails. + */ + assert : function (condition, message){ + YUITest.Assert._increment(); + if (!condition){ + throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, "Assertion failed.")); + } + }, + + /** + * Forces an assertion error to occur. Shortcut for YUITest.Assert.fail(). + * @method fail + * @param {String} message (Optional) The message to display with the failure. + */ + fail: function (message) { + YUITest.Assert.fail(message); + }, + + //------------------------------------------------------------------------- + // Stub Methods + //------------------------------------------------------------------------- + + /** + * Function to run once before tests start to run. + * This executes before the first call to setUp(). + */ + init: function(){ + //noop + }, + + /** + * Function to run once after tests finish running. + * This executes after the last call to tearDown(). + */ + destroy: function(){ + //noop + }, + + /** + * Function to run before each test is executed. + * @return {Void} + * @method setUp + */ + setUp : function () { + //noop + }, + + /** + * Function to run after each test is executed. + * @return {Void} + * @method tearDown + */ + tearDown: function () { + //noop + } +}; + + + +/** + * A test suite that can contain a collection of TestCase and TestSuite objects. + * @param {String||Object} data The name of the test suite or an object containing + * a name property as well as setUp and tearDown methods. + * @namespace YUITest + * @class TestSuite + * @constructor + */ +YUITest.TestSuite = function (data) { + + /** + * The name of the test suite. + * @type String + * @property name + */ + this.name = ""; + + /** + * Array of test suites and test cases. + * @type Array + * @property items + * @private + */ + this.items = []; + + //initialize the properties + if (typeof data == "string"){ + this.name = data; + } else if (data instanceof Object){ + for (var prop in data){ + if (data.hasOwnProperty(prop)){ + this[prop] = data[prop]; + } + } + } + + //double-check name + if (this.name === ""){ + this.name = "testSuite" + (+new Date()); + } + +}; + +YUITest.TestSuite.prototype = { + + //restore constructor + constructor: YUITest.TestSuite, + + /** + * Adds a test suite or test case to the test suite. + * @param {YUITest.TestSuite||YUITest.TestCase} testObject The test suite or test case to add. + * @return {Void} + * @method add + */ + add : function (testObject) { + if (testObject instanceof YUITest.TestSuite || testObject instanceof YUITest.TestCase) { + this.items.push(testObject); + } + return this; + }, + + //------------------------------------------------------------------------- + // Stub Methods + //------------------------------------------------------------------------- + + /** + * Function to run before each test is executed. + * @return {Void} + * @method setUp + */ + setUp : function () { + }, + + /** + * Function to run after each test is executed. + * @return {Void} + * @method tearDown + */ + tearDown: function () { + } + +}; + +/** + * An object object containing test result formatting methods. + * @namespace YUITest + * @class TestFormat + * @static + */ +YUITest.TestFormat = function(){ + + /* (intentionally not documented) + * Basic XML escaping method. Replaces quotes, less-than, greater-than, + * apostrophe, and ampersand characters with their corresponding entities. + * @param {String} text The text to encode. + * @return {String} The XML-escaped text. + */ + function xmlEscape(text){ + + return text.replace(/[<>"'&]/g, function(value){ + switch(value){ + case "<": return "<"; + case ">": return ">"; + case "\"": return """; + case "'": return "'"; + case "&": return "&"; + } + }); + + } + + + return { + + /** + * Returns test results formatted as a JSON string. Requires JSON utility. + * @param {Object} result The results object created by TestRunner. + * @return {String} A JSON-formatted string of results. + * @method JSON + * @static + */ + JSON: function(results) { + return YUITest.Util.JSON.stringify(results); + }, + + /** + * Returns test results formatted as an XML string. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @method XML + * @static + */ + XML: function(results) { + + function serializeToXML(results){ + var xml = "<" + results.type + " name=\"" + xmlEscape(results.name) + "\""; + + if (typeof(results.duration)=="number"){ + xml += " duration=\"" + results.duration + "\""; + } + + if (results.type == "test"){ + xml += " result=\"" + results.result + "\" message=\"" + xmlEscape(results.message) + "\">"; + } else { + xml += " passed=\"" + results.passed + "\" failed=\"" + results.failed + "\" ignored=\"" + results.ignored + "\" total=\"" + results.total + "\">"; + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToXML(results[prop]); + } + } + } + } + + xml += ""; + + return xml; + } + + return "" + serializeToXML(results); + + }, + + + /** + * Returns test results formatted in JUnit XML format. + * @param {Object} result The results object created by TestRunner. + * @return {String} An XML-formatted string of results. + * @method JUnitXML + * @static + */ + JUnitXML: function(results) { + + function serializeToJUnitXML(results){ + var xml = ""; + + switch (results.type){ + //equivalent to testcase in JUnit + case "test": + if (results.result != "ignore"){ + xml = ""; + if (results.result == "fail"){ + xml += ""; + } + xml+= ""; + } + break; + + //equivalent to testsuite in JUnit + case "testcase": + + xml = ""; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + + xml += ""; + break; + + //no JUnit equivalent, don't output anything + case "testsuite": + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + break; + + //top-level, equivalent to testsuites in JUnit + case "report": + + xml = ""; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + xml += serializeToJUnitXML(results[prop]); + } + } + } + + xml += ""; + + //no default + } + + return xml; + + } + + return "" + serializeToJUnitXML(results); + }, + + /** + * Returns test results formatted in TAP format. + * For more information, see Test Anything Protocol. + * @param {Object} result The results object created by TestRunner. + * @return {String} A TAP-formatted string of results. + * @method TAP + * @static + */ + TAP: function(results) { + + var currentTestNum = 1; + + function serializeToTAP(results){ + var text = ""; + + switch (results.type){ + + case "test": + if (results.result != "ignore"){ + + text = "ok " + (currentTestNum++) + " - " + results.name; + + if (results.result == "fail"){ + text = "not " + text + " - " + results.message; + } + + text += "\n"; + } else { + text = "#Ignored test " + results.name + "\n"; + } + break; + + case "testcase": + + text = "#Begin testcase " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + text += "#End testcase " + results.name + "\n"; + + + break; + + case "testsuite": + + text = "#Begin testsuite " + results.name + "(" + results.failed + " failed of " + results.total + ")\n"; + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + text += "#End testsuite " + results.name + "\n"; + break; + + case "report": + + for (var prop in results){ + if (results.hasOwnProperty(prop)){ + if (results[prop] && typeof results[prop] == "object" && !(results[prop] instanceof Array)){ + text += serializeToTAP(results[prop]); + } + } + } + + //no default + } + + return text; + + } + + return "1.." + results.total + "\n" + serializeToTAP(results); + } + + }; +}(); + +/** + * An object object containing coverage result formatting methods. + * @namespace YUITest + * @class CoverageFormat + * @static + */ +YUITest.CoverageFormat = { + + /** + * Returns the coverage report in JSON format. This is the straight + * JSON representation of the native coverage report. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method JSON + * @namespace YUITest.CoverageFormat + */ + JSON: function(coverage){ + return YUITest.Util.JSON.stringify(coverage); + }, + + /** + * Returns the coverage report in a JSON format compatible with + * Xdebug. See Xdebug Documentation + * for more information. Note: function coverage is not available + * in this format. + * @param {Object} coverage The coverage report object. + * @return {String} A JSON-formatted string of coverage data. + * @method XdebugJSON + * @namespace YUITest.CoverageFormat + */ + XdebugJSON: function(coverage){ + + var report = {}; + for (var prop in coverage){ + if (coverage.hasOwnProperty(prop)){ + report[prop] = coverage[prop].lines; + } + } + + return YUITest.Util.JSON.stringify(coverage); + } + +}; + + +/** + * An object object containing methods to simulate browser events. + * @namespace YUITest + * @class Event + * @static + */ +YUITest.Event = (function() { + + var + + //mouse events supported + mouseEvents = { + click: 1, + dblclick: 1, + mouseover: 1, + mouseout: 1, + mousedown: 1, + mouseup: 1, + mousemove: 1 + }, + + //key events supported + keyEvents = { + keydown: 1, + keyup: 1, + keypress: 1 + }, + + //HTML events supported + uiEvents = { + blur: 1, + change: 1, + focus: 1, + resize: 1, + scroll: 1, + select: 1 + }, + + //events that bubble by default + bubbleEvents = { + scroll: 1, + resize: 1, + reset: 1, + submit: 1, + change: 1, + select: 1, + error: 1, + abort: 1, + + //also mouse events + click: 1, + dblclick: 1, + mouseover: 1, + mouseout: 1, + mousedown: 1, + mouseup: 1, + mousemove: 1, + + //and keyboard events + keydown: 1, + keyup: 1, + keypress: 1 + + }, + + //the object to return + object, + + //used for property name iteration + prop; + + /* + * Note: Intentionally not for YUIDoc generation. + * Simulates a key event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. Note: keydown causes Safari 2.x to + * crash. + * @method simulateKeyEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: keyup, keydown, and keypress. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 3 specifies that all key events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 3 specifies that all + * key events can be cancelled. The default + * is true. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} keyCode (Optional) The code for the key that is in use. + * The default is 0. + * @param {int} charCode (Optional) The Unicode code for the character + * associated with the key being used. The default is 0. + */ + function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + keyCode /*:int*/, charCode /*:int*/) /*:Void*/ + { + //check target + if (!target){ + throw new Error("simulateKeyEvent(): Invalid target."); + } + + //check event type + if (typeof type == "string"){ + type = type.toLowerCase(); + switch(type){ + case "textevent": //DOM Level 3 + type = "keypress"; + break; + case "keyup": + case "keydown": + case "keypress": + break; + default: + throw new Error("simulateKeyEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateKeyEvent(): Event type must be a string."); + } + + //setup default values + if (typeof bubbles != "boolean"){ + bubbles = true; //all key events bubble + } + if (typeof cancelable != "boolean"){ + cancelable = true; //all key events can be cancelled + } + if (typeof view != "object" || view == null){ + view = window; //view is typically window + } + if (typeof ctrlKey != "boolean"){ + ctrlKey = false; + } + if (typeof altKey != "boolean"){ + altKey = false; + } + if (typeof shiftKey != "boolean"){ + shiftKey = false; + } + if (typeof metaKey != "boolean"){ + metaKey = false; + } + if (typeof keyCode != "number"){ + keyCode = 0; + } + if (typeof charCode != "number"){ + charCode = 0; + } + + //try to create a mouse event + var customEvent = null; + + //check for DOM-compliant browsers first + if (typeof document.createEvent == "function"){ + + try { + + //try to create key event + customEvent = document.createEvent("KeyEvents"); + + /* + * Interesting problem: Firefox implemented a non-standard + * version of initKeyEvent() based on DOM Level 2 specs. + * Key event was removed from DOM Level 2 and re-introduced + * in DOM Level 3 with a different interface. Firefox is the + * only browser with any implementation of Key Events, so for + * now, assume it's Firefox if the above line doesn't error. + */ + // @TODO: Decipher between Firefox's implementation and a correct one. + customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey, + altKey, shiftKey, metaKey, keyCode, charCode); + + } catch (ex){ + + /* + * If it got here, that means key events aren't officially supported. + * Safari/WebKit is a real problem now. WebKit 522 won't let you + * set keyCode, charCode, or other properties if you use a + * UIEvent, so we first must try to create a generic event. The + * fun part is that this will throw an error on Safari 2.x. The + * end result is that we need another try...catch statement just to + * deal with this mess. + */ + try { + + //try to create generic event - will fail in Safari 2.x + customEvent = document.createEvent("Events"); + + } catch (uierror /*:Error*/){ + + //the above failed, so create a UIEvent for Safari 2.x + customEvent = document.createEvent("UIEvents"); + + } finally { + + customEvent.initEvent(type, bubbles, cancelable); + + //initialize + customEvent.view = view; + customEvent.altKey = altKey; + customEvent.ctrlKey = ctrlKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + customEvent.keyCode = keyCode; + customEvent.charCode = charCode; + + } + + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (typeof document.createEventObject != "undefined"){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.shiftKey = shiftKey; + customEvent.metaKey = metaKey; + + /* + * IE doesn't support charCode explicitly. CharCode should + * take precedence over any keyCode value for accurate + * representation. + */ + customEvent.keyCode = (charCode > 0) ? charCode : keyCode; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateKeyEvent(): No event simulation framework present."); + } + } + + /* + * Note: Intentionally not for YUIDoc generation. + * Simulates a mouse event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. + * @method simulateMouseEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 2 specifies that all mouse events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 2 specifies that all + * mouse events except mousemove can be cancelled. The default + * is true for all events except mousemove, for which the default + * is false. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {int} detail (Optional) The number of times the mouse button has + * been used. The default value is 1. + * @param {int} screenX (Optional) The x-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} screenY (Optional) The y-coordinate on the screen at which + * point the event occured. The default is 0. + * @param {int} clientX (Optional) The x-coordinate on the client at which + * point the event occured. The default is 0. + * @param {int} clientY (Optional) The y-coordinate on the client at which + * point the event occured. The default is 0. + * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys + * is pressed while the event is firing. The default is false. + * @param {Boolean} metaKey (Optional) Indicates if one of the META keys + * is pressed while the event is firing. The default is false. + * @param {int} button (Optional) The button being pressed while the event + * is executing. The value should be 0 for the primary mouse button + * (typically the left button), 1 for the terciary mouse button + * (typically the middle button), and 2 for the secondary mouse button + * (typically the right button). The default is 0. + * @param {HTMLElement} relatedTarget (Optional) For mouseout events, + * this is the element that the mouse has moved to. For mouseover + * events, this is the element that the mouse has moved from. This + * argument is ignored for all other events. The default is null. + */ + function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, detail /*:int*/, + screenX /*:int*/, screenY /*:int*/, + clientX /*:int*/, clientY /*:int*/, + ctrlKey /*:Boolean*/, altKey /*:Boolean*/, + shiftKey /*:Boolean*/, metaKey /*:Boolean*/, + button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/ + { + + //check target + if (!target){ + throw new Error("simulateMouseEvent(): Invalid target."); + } + + //check event type + if (typeof type == "string"){ + type = type.toLowerCase(); + + //make sure it's a supported mouse event + if (!mouseEvents[type]){ + throw new Error("simulateMouseEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateMouseEvent(): Event type must be a string."); + } + + //setup default values + if (typeof bubbles != "boolean"){ + bubbles = true; //all mouse events bubble + } + if (typeof cancelable != "boolean"){ + cancelable = (type != "mousemove"); //mousemove is the only one that can't be cancelled + } + if (typeof view != "object" || view != null){ + view = window; //view is typically window + } + if (typeof detail != "number"){ + detail = 1; //number of mouse clicks must be at least one + } + if (typeof screenX != "number"){ + screenX = 0; + } + if (typeof screenY != "number"){ + screenY = 0; + } + if (typeof clientX != "number"){ + clientX = 0; + } + if (typeof clientY != "number"){ + clientY = 0; + } + if (typeof ctrlKey != "boolean"){ + ctrlKey = false; + } + if (typeof altKey != "boolean"){ + altKey = false; + } + if (typeof shiftKey != "boolean"){ + shiftKey = false; + } + if (typeof metaKey != "boolean"){ + metaKey = false; + } + if (typeof button != "number"){ + button = 0; + } + + if (!relatedTarget){ + relatedTarget = null; + } + + //try to create a mouse event + var customEvent /*:MouseEvent*/ = null; + + //check for DOM-compliant browsers first + if (typeof document.createEvent == "function"){ + + customEvent = document.createEvent("MouseEvents"); + + //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() + if (customEvent.initMouseEvent){ + customEvent.initMouseEvent(type, bubbles, cancelable, view, detail, + screenX, screenY, clientX, clientY, + ctrlKey, altKey, shiftKey, metaKey, + button, relatedTarget); + } else { //Safari + + //the closest thing available in Safari 2.x is UIEvents + customEvent = document.createEvent("UIEvents"); + customEvent.initEvent(type, bubbles, cancelable); + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + customEvent.button = button; + customEvent.relatedTarget = relatedTarget; + } + + /* + * Check to see if relatedTarget has been assigned. Firefox + * versions less than 2.0 don't allow it to be assigned via + * initMouseEvent() and the property is readonly after event + * creation, so in order to keep YAHOO.util.getRelatedTarget() + * working, assign to the IE proprietary toElement property + * for mouseout event and fromElement property for mouseover + * event. + */ + if (relatedTarget && !customEvent.relatedTarget){ + if (type == "mouseout"){ + customEvent.toElement = relatedTarget; + } else if (type == "mouseover"){ + customEvent.fromElement = relatedTarget; + } + } + + //fire the event + target.dispatchEvent(customEvent); + + } else if (typeof document.createEventObject != "undefined"){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.detail = detail; + customEvent.screenX = screenX; + customEvent.screenY = screenY; + customEvent.clientX = clientX; + customEvent.clientY = clientY; + customEvent.ctrlKey = ctrlKey; + customEvent.altKey = altKey; + customEvent.metaKey = metaKey; + customEvent.shiftKey = shiftKey; + + //fix button property for IE's wacky implementation + switch(button){ + case 0: + customEvent.button = 1; + break; + case 1: + customEvent.button = 4; + break; + case 2: + //leave as is + break; + default: + customEvent.button = 0; + } + + /* + * Have to use relatedTarget because IE won't allow assignment + * to toElement or fromElement on generic events. This keeps + * YAHOO.util.customEvent.getRelatedTarget() functional. + */ + customEvent.relatedTarget = relatedTarget; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateMouseEvent(): No event simulation framework present."); + } + } + + /* + * Note: Intentionally not for YUIDoc generation. + * Simulates a UI event using the given event information to populate + * the generated event object. This method does browser-equalizing + * calculations to account for differences in the DOM and IE event models + * as well as different browser quirks. + * @method simulateHTMLEvent + * @private + * @static + * @param {HTMLElement} target The target of the given event. + * @param {String} type The type of event to fire. This can be any one of + * the following: click, dblclick, mousedown, mouseup, mouseout, + * mouseover, and mousemove. + * @param {Boolean} bubbles (Optional) Indicates if the event can be + * bubbled up. DOM Level 2 specifies that all mouse events bubble by + * default. The default is true. + * @param {Boolean} cancelable (Optional) Indicates if the event can be + * canceled using preventDefault(). DOM Level 2 specifies that all + * mouse events except mousemove can be cancelled. The default + * is true for all events except mousemove, for which the default + * is false. + * @param {Window} view (Optional) The view containing the target. This is + * typically the window object. The default is window. + * @param {int} detail (Optional) The number of times the mouse button has + * been used. The default value is 1. + */ + function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/, + bubbles /*:Boolean*/, cancelable /*:Boolean*/, + view /*:Window*/, detail /*:int*/) /*:Void*/ + { + + //check target + if (!target){ + throw new Error("simulateUIEvent(): Invalid target."); + } + + //check event type + if (typeof type == "string"){ + type = type.toLowerCase(); + + //make sure it's a supported mouse event + if (!uiEvents[type]){ + throw new Error("simulateUIEvent(): Event type '" + type + "' not supported."); + } + } else { + throw new Error("simulateUIEvent(): Event type must be a string."); + } + + //try to create a mouse event + var customEvent = null; + + + //setup default values + if (typeof bubbles != "boolean"){ + bubbles = (type in bubbleEvents); //not all events bubble + } + if (typeof cancelable != "boolean"){ + cancelable = (type == "submit"); //submit is the only one that can be cancelled + } + if (typeof view != "object" || view != null){ + view = window; //view is typically window + } + if (typeof detail != "number"){ + detail = 1; //usually not used but defaulted to this + } + + //check for DOM-compliant browsers first + if (typeof document.createEvent == "function"){ + + //just a generic UI Event object is needed + customEvent = document.createEvent("UIEvents"); + customEvent.initUIEvent(type, bubbles, cancelable, view, detail); + + //fire the event + target.dispatchEvent(customEvent); + + } else if (typeof document.createEventObject != "undefined"){ //IE + + //create an IE event object + customEvent = document.createEventObject(); + + //assign available properties + customEvent.bubbles = bubbles; + customEvent.cancelable = cancelable; + customEvent.view = view; + customEvent.detail = detail; + + //fire the event + target.fireEvent("on" + type, customEvent); + + } else { + throw new Error("simulateUIEvent(): No event simulation framework present."); + } + } + + + /** + * Allows event simulation for browser-based events. + * @namespace YUITest + * @class Event + * @static + */ + object = { + + /** + * Simulates the event with the given name on a target. + * @param {HTMLElement} target The DOM element that's the target of the event. + * @param {String} type The type of event to simulate (i.e., "click"). + * @param {Object} options (Optional) Extra options to copy onto the event object. + * @return {void} + * @method simulate + * @static + * @deprecated + */ + simulate: function(target, type, options){ + + options = options || {}; + + if (mouseEvents[type]){ + simulateMouseEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail, options.screenX, + options.screenY, options.clientX, options.clientY, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, options.button, + options.relatedTarget); + } else if (keyEvents[type]){ + simulateKeyEvent(target, type, options.bubbles, + options.cancelable, options.view, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, + options.keyCode, options.charCode); + } else if (uiEvents[type]){ + simulateUIEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail); + } else { + throw new Error("simulate(): Event '" + type + "' can't be simulated."); + } + } + }; + + //create the convenience methods for mouse events + for (prop in mouseEvents){ + if (mouseEvents.hasOwnProperty(prop)){ + object[prop] = (function(type){ + return function(target, options){ + options = options || {}; + simulateMouseEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail, options.screenX, + options.screenY, options.clientX, options.clientY, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, options.button, + options.relatedTarget); + }; + })(prop); + } + } + + //create the convenience methods for key events + for (prop in keyEvents){ + if (keyEvents.hasOwnProperty(prop)){ + object[prop] = (function(type){ + return function(target, options){ + options = options || {}; + simulateKeyEvent(target, type, options.bubbles, + options.cancelable, options.view, options.ctrlKey, + options.altKey, options.shiftKey, options.metaKey, + options.keyCode, options.charCode); + }; + })(prop); + } + } + + //create the convenience methods for key events + for (prop in uiEvents){ + if (uiEvents.hasOwnProperty(prop)){ + object[prop] = (function(type){ + return function(target, options){ + options = options || {}; + simulateUIEvent(target, type, options.bubbles, + options.cancelable, options.view, options.detail); + }; + })(prop); + } + } + + return object; + +})(); + + + /** + * An object capable of sending test results to a server. + * @param {String} url The URL to submit the results to. + * @param {Function} format (Optiona) A function that outputs the results in a specific format. + * Default is YUITest.TestFormat.XML. + * @constructor + * @namespace YUITest + * @class Reporter + */ + YUITest.Reporter = function(url, format) { + + /** + * The URL to submit the data to. + * @type String + * @property url + */ + this.url = url; + + /** + * The formatting function to call when submitting the data. + * @type Function + * @property format + */ + this.format = format || YUITest.TestFormat.XML; + + /** + * Extra fields to submit with the request. + * @type Object + * @property _fields + * @private + */ + this._fields = new Object(); + + /** + * The form element used to submit the results. + * @type HTMLFormElement + * @property _form + * @private + */ + this._form = null; + + /** + * Iframe used as a target for form submission. + * @type HTMLIFrameElement + * @property _iframe + * @private + */ + this._iframe = null; + }; + + YUITest.Reporter.prototype = { + + //restore missing constructor + constructor: YUITest.Reporter, + + /** + * Adds a field to the form that submits the results. + * @param {String} name The name of the field. + * @param {Variant} value The value of the field. + * @return {Void} + * @method addField + */ + addField : function (name, value){ + this._fields[name] = value; + }, + + /** + * Removes all previous defined fields. + * @return {Void} + * @method addField + */ + clearFields : function(){ + this._fields = new Object(); + }, + + /** + * Cleans up the memory associated with the TestReporter, removing DOM elements + * that were created. + * @return {Void} + * @method destroy + */ + destroy : function() { + if (this._form){ + this._form.parentNode.removeChild(this._form); + this._form = null; + } + if (this._iframe){ + this._iframe.parentNode.removeChild(this._iframe); + this._iframe = null; + } + this._fields = null; + }, + + /** + * Sends the report to the server. + * @param {Object} results The results object created by TestRunner. + * @return {Void} + * @method report + */ + report : function(results){ + + //if the form hasn't been created yet, create it + if (!this._form){ + this._form = document.createElement("form"); + this._form.method = "post"; + this._form.style.visibility = "hidden"; + this._form.style.position = "absolute"; + this._form.style.top = 0; + document.body.appendChild(this._form); + + //IE won't let you assign a name using the DOM, must do it the hacky way + try { + this._iframe = document.createElement("

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