summaryrefslogtreecommitdiffstats
path: root/apps/it/static/js/ui/external
diff options
context:
space:
mode:
Diffstat (limited to 'apps/it/static/js/ui/external')
-rw-r--r--apps/it/static/js/ui/external/globalize.culture.de-DE.js81
-rw-r--r--apps/it/static/js/ui/external/globalize.culture.ja-JP.js100
-rw-r--r--apps/it/static/js/ui/external/globalize.js1585
-rw-r--r--apps/it/static/js/ui/external/jquery.mousewheel.js101
-rw-r--r--apps/it/static/js/ui/external/jshint.js4835
-rw-r--r--apps/it/static/js/ui/external/qunit.css244
-rw-r--r--apps/it/static/js/ui/external/qunit.js2152
7 files changed, 0 insertions, 9098 deletions
diff --git a/apps/it/static/js/ui/external/globalize.culture.de-DE.js b/apps/it/static/js/ui/external/globalize.culture.de-DE.js
deleted file mode 100644
index 5466bd7..0000000
--- a/apps/it/static/js/ui/external/globalize.culture.de-DE.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Globalize Culture de-DE
- *
- * http://github.com/jquery/globalize
- *
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * This file was generated by the Globalize Culture Generator
- * Translation: bugs found in this file need to be fixed in the generator
- */
-
-(function( window, undefined ) {
-
-var Globalize;
-
-if ( typeof require !== "undefined"
- && typeof exports !== "undefined"
- && typeof module !== "undefined" ) {
- // Assume CommonJS
- Globalize = require( "globalize" );
-} else {
- // Global variable
- Globalize = window.Globalize;
-}
-
-Globalize.addCultureInfo( "de-DE", "default", {
- name: "de-DE",
- englishName: "German (Germany)",
- nativeName: "Deutsch (Deutschland)",
- language: "de",
- numberFormat: {
- ",": ".",
- ".": ",",
- NaN: "n. def.",
- negativeInfinity: "-unendlich",
- positiveInfinity: "+unendlich",
- percent: {
- pattern: ["-n%","n%"],
- ",": ".",
- ".": ","
- },
- currency: {
- pattern: ["-n $","n $"],
- ",": ".",
- ".": ",",
- symbol: "€"
- }
- },
- calendars: {
- standard: {
- "/": ".",
- firstDay: 1,
- days: {
- names: ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],
- namesAbbr: ["So","Mo","Di","Mi","Do","Fr","Sa"],
- namesShort: ["So","Mo","Di","Mi","Do","Fr","Sa"]
- },
- months: {
- names: ["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember",""],
- namesAbbr: ["Jan","Feb","Mrz","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez",""]
- },
- AM: null,
- PM: null,
- eras: [{"name":"n. Chr.","start":null,"offset":0}],
- patterns: {
- d: "dd.MM.yyyy",
- D: "dddd, d. MMMM yyyy",
- t: "HH:mm",
- T: "HH:mm:ss",
- f: "dddd, d. MMMM yyyy HH:mm",
- F: "dddd, d. MMMM yyyy HH:mm:ss",
- M: "dd MMMM",
- Y: "MMMM yyyy"
- }
- }
- }
-});
-
-}( this ));
diff --git a/apps/it/static/js/ui/external/globalize.culture.ja-JP.js b/apps/it/static/js/ui/external/globalize.culture.ja-JP.js
deleted file mode 100644
index a9469d7..0000000
--- a/apps/it/static/js/ui/external/globalize.culture.ja-JP.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Globalize Culture ja-JP
- *
- * http://github.com/jquery/globalize
- *
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * This file was generated by the Globalize Culture Generator
- * Translation: bugs found in this file need to be fixed in the generator
- */
-
-(function( window, undefined ) {
-
-var Globalize;
-
-if ( typeof require !== "undefined"
- && typeof exports !== "undefined"
- && typeof module !== "undefined" ) {
- // Assume CommonJS
- Globalize = require( "globalize" );
-} else {
- // Global variable
- Globalize = window.Globalize;
-}
-
-Globalize.addCultureInfo( "ja-JP", "default", {
- name: "ja-JP",
- englishName: "Japanese (Japan)",
- nativeName: "日本語 (日本)",
- language: "ja",
- numberFormat: {
- NaN: "NaN (非数値)",
- negativeInfinity: "-∞",
- positiveInfinity: "+∞",
- percent: {
- pattern: ["-n%","n%"]
- },
- currency: {
- pattern: ["-$n","$n"],
- decimals: 0,
- symbol: "¥"
- }
- },
- calendars: {
- standard: {
- days: {
- names: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
- namesAbbr: ["日","月","火","水","木","金","土"],
- namesShort: ["日","月","火","水","木","金","土"]
- },
- months: {
- names: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月",""],
- namesAbbr: ["1","2","3","4","5","6","7","8","9","10","11","12",""]
- },
- AM: ["午前","午前","午前"],
- PM: ["午後","午後","午後"],
- eras: [{"name":"西暦","start":null,"offset":0}],
- patterns: {
- d: "yyyy/MM/dd",
- D: "yyyy'年'M'月'd'日'",
- t: "H:mm",
- T: "H:mm:ss",
- f: "yyyy'年'M'月'd'日' H:mm",
- F: "yyyy'年'M'月'd'日' H:mm:ss",
- M: "M'月'd'日'",
- Y: "yyyy'年'M'月'"
- }
- },
- Japanese: {
- name: "Japanese",
- days: {
- names: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
- namesAbbr: ["日","月","火","水","木","金","土"],
- namesShort: ["日","月","火","水","木","金","土"]
- },
- months: {
- names: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月",""],
- namesAbbr: ["1","2","3","4","5","6","7","8","9","10","11","12",""]
- },
- AM: ["午前","午前","午前"],
- PM: ["午後","午後","午後"],
- eras: [{"name":"平成","start":null,"offset":1867},{"name":"昭和","start":-1812153600000,"offset":1911},{"name":"大正","start":-1357603200000,"offset":1925},{"name":"明治","start":60022080000,"offset":1988}],
- twoDigitYearMax: 99,
- patterns: {
- d: "gg y/M/d",
- D: "gg y'年'M'月'd'日'",
- t: "H:mm",
- T: "H:mm:ss",
- f: "gg y'年'M'月'd'日' H:mm",
- F: "gg y'年'M'月'd'日' H:mm:ss",
- M: "M'月'd'日'",
- Y: "gg y'年'M'月'"
- }
- }
- }
-});
-
-}( this ));
diff --git a/apps/it/static/js/ui/external/globalize.js b/apps/it/static/js/ui/external/globalize.js
deleted file mode 100644
index a38a326..0000000
--- a/apps/it/static/js/ui/external/globalize.js
+++ /dev/null
@@ -1,1585 +0,0 @@
-/*!
- * Globalize
- *
- * http://github.com/jquery/globalize
- *
- * Copyright Software Freedom Conservancy, Inc.
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- */
-
-(function( window, undefined ) {
-
-var Globalize,
- // private variables
- regexHex,
- regexInfinity,
- regexParseFloat,
- regexTrim,
- // private JavaScript utility functions
- arrayIndexOf,
- endsWith,
- extend,
- isArray,
- isFunction,
- isObject,
- startsWith,
- trim,
- truncate,
- zeroPad,
- // private Globalization utility functions
- appendPreOrPostMatch,
- expandFormat,
- formatDate,
- formatNumber,
- getTokenRegExp,
- getEra,
- getEraYear,
- parseExact,
- parseNegativePattern;
-
-// Global variable (Globalize) or CommonJS module (globalize)
-Globalize = function( cultureSelector ) {
- return new Globalize.prototype.init( cultureSelector );
-};
-
-if ( typeof require !== "undefined" &&
- typeof exports !== "undefined" &&
- typeof module !== "undefined" ) {
- // Assume CommonJS
- module.exports = Globalize;
-} else {
- // Export as global variable
- window.Globalize = Globalize;
-}
-
-Globalize.cultures = {};
-
-Globalize.prototype = {
- constructor: Globalize,
- init: function( cultureSelector ) {
- this.cultures = Globalize.cultures;
- this.cultureSelector = cultureSelector;
-
- return this;
- }
-};
-Globalize.prototype.init.prototype = Globalize.prototype;
-
-// 1. When defining a culture, all fields are required except the ones stated as optional.
-// 2. Each culture should have a ".calendars" object with at least one calendar named "standard"
-// which serves as the default calendar in use by that culture.
-// 3. Each culture should have a ".calendar" object which is the current calendar being used,
-// it may be dynamically changed at any time to one of the calendars in ".calendars".
-Globalize.cultures[ "default" ] = {
- // A unique name for the culture in the form <language code>-<country/region code>
- name: "en",
- // the name of the culture in the english language
- englishName: "English",
- // the name of the culture in its own language
- nativeName: "English",
- // whether the culture uses right-to-left text
- isRTL: false,
- // "language" is used for so-called "specific" cultures.
- // For example, the culture "es-CL" means "Spanish, in Chili".
- // It represents the Spanish-speaking culture as it is in Chili,
- // which might have different formatting rules or even translations
- // than Spanish in Spain. A "neutral" culture is one that is not
- // specific to a region. For example, the culture "es" is the generic
- // Spanish culture, which may be a more generalized version of the language
- // that may or may not be what a specific culture expects.
- // For a specific culture like "es-CL", the "language" field refers to the
- // neutral, generic culture information for the language it is using.
- // This is not always a simple matter of the string before the dash.
- // For example, the "zh-Hans" culture is netural (Simplified Chinese).
- // And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
- // field is "zh-CHS", not "zh".
- // This field should be used to navigate from a specific culture to it's
- // more general, neutral culture. If a culture is already as general as it
- // can get, the language may refer to itself.
- language: "en",
- // numberFormat defines general number formatting rules, like the digits in
- // each grouping, the group separator, and how negative numbers are displayed.
- numberFormat: {
- // [negativePattern]
- // Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
- // but is still defined as an array for consistency with them.
- // negativePattern: one of "(n)|-n|- n|n-|n -"
- pattern: [ "-n" ],
- // number of decimal places normally shown
- decimals: 2,
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // symbol used for positive numbers
- "+": "+",
- // symbol used for negative numbers
- "-": "-",
- // symbol used for NaN (Not-A-Number)
- "NaN": "NaN",
- // symbol used for Negative Infinity
- negativeInfinity: "-Infinity",
- // symbol used for Positive Infinity
- positiveInfinity: "Infinity",
- percent: {
- // [negativePattern, positivePattern]
- // negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
- // positivePattern: one of "n %|n%|%n|% n"
- pattern: [ "-n %", "n %" ],
- // number of decimal places normally shown
- decimals: 2,
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // symbol used to represent a percentage
- symbol: "%"
- },
- currency: {
- // [negativePattern, positivePattern]
- // negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
- // positivePattern: one of "$n|n$|$ n|n $"
- pattern: [ "($n)", "$n" ],
- // number of decimal places normally shown
- decimals: 2,
- // array of numbers indicating the size of each number group.
- // TODO: more detailed description and example
- groupSizes: [ 3 ],
- // string that separates number groups, as in 1,000,000
- ",": ",",
- // string that separates a number from the fractional portion, as in 1.99
- ".": ".",
- // symbol used to represent currency
- symbol: "$"
- }
- },
- // calendars defines all the possible calendars used by this culture.
- // There should be at least one defined with name "standard", and is the default
- // calendar used by the culture.
- // A calendar contains information about how dates are formatted, information about
- // the calendar's eras, a standard set of the date formats,
- // translations for day and month names, and if the calendar is not based on the Gregorian
- // calendar, conversion functions to and from the Gregorian calendar.
- calendars: {
- standard: {
- // name that identifies the type of calendar this is
- name: "Gregorian_USEnglish",
- // separator of parts of a date (e.g. "/" in 11/05/1955)
- "/": "/",
- // separator of parts of a time (e.g. ":" in 05:44 PM)
- ":": ":",
- // the first day of the week (0 = Sunday, 1 = Monday, etc)
- firstDay: 0,
- days: {
- // full day names
- names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
- // abbreviated day names
- namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
- // shortest day names
- namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
- },
- months: {
- // full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
- names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
- // abbreviated month names
- namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
- },
- // AM and PM designators in one of these forms:
- // The usual view, and the upper and lower case versions
- // [ standard, lowercase, uppercase ]
- // The culture does not use AM or PM (likely all standard date formats use 24 hour time)
- // null
- AM: [ "AM", "am", "AM" ],
- PM: [ "PM", "pm", "PM" ],
- eras: [
- // eras in reverse chronological order.
- // name: the name of the era in this culture (e.g. A.D., C.E.)
- // start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
- // offset: offset in years from gregorian calendar
- {
- "name": "A.D.",
- "start": null,
- "offset": 0
- }
- ],
- // when a two digit year is given, it will never be parsed as a four digit
- // year greater than this year (in the appropriate era for the culture)
- // Set it as a full year (e.g. 2029) or use an offset format starting from
- // the current year: "+19" would correspond to 2029 if the current year 2010.
- twoDigitYearMax: 2029,
- // set of predefined date and time patterns used by the culture
- // these represent the format someone in this culture would expect
- // to see given the portions of the date that are shown.
- patterns: {
- // short date pattern
- d: "M/d/yyyy",
- // long date pattern
- D: "dddd, MMMM dd, yyyy",
- // short time pattern
- t: "h:mm tt",
- // long time pattern
- T: "h:mm:ss tt",
- // long date, short time pattern
- f: "dddd, MMMM dd, yyyy h:mm tt",
- // long date, long time pattern
- F: "dddd, MMMM dd, yyyy h:mm:ss tt",
- // month/day pattern
- M: "MMMM dd",
- // month/year pattern
- Y: "yyyy MMMM",
- // S is a sortable format that does not vary by culture
- S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
- }
- // optional fields for each calendar:
- /*
- monthsGenitive:
- Same as months but used when the day preceeds the month.
- Omit if the culture has no genitive distinction in month names.
- For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
- convert:
- Allows for the support of non-gregorian based calendars. This convert object is used to
- to convert a date to and from a gregorian calendar date to handle parsing and formatting.
- The two functions:
- fromGregorian( date )
- Given the date as a parameter, return an array with parts [ year, month, day ]
- corresponding to the non-gregorian based year, month, and day for the calendar.
- toGregorian( year, month, day )
- Given the non-gregorian year, month, and day, return a new Date() object
- set to the corresponding date in the gregorian calendar.
- */
- }
- },
- // For localized strings
- messages: {}
-};
-
-Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;
-
-Globalize.cultures.en = Globalize.cultures[ "default" ];
-
-Globalize.cultureSelector = "en";
-
-//
-// private variables
-//
-
-regexHex = /^0x[a-f0-9]+$/i;
-regexInfinity = /^[+\-]?infinity$/i;
-regexParseFloat = /^[+\-]?\d*\.?\d*(e[+\-]?\d+)?$/;
-regexTrim = /^\s+|\s+$/g;
-
-//
-// private JavaScript utility functions
-//
-
-arrayIndexOf = function( array, item ) {
- if ( array.indexOf ) {
- return array.indexOf( item );
- }
- for ( var i = 0, length = array.length; i < length; i++ ) {
- if ( array[i] === item ) {
- return i;
- }
- }
- return -1;
-};
-
-endsWith = function( value, pattern ) {
- return value.substr( value.length - pattern.length ) === pattern;
-};
-
-extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !isFunction(target) ) {
- target = {};
- }
-
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && isArray(src) ? src : [];
-
- } else {
- clone = src && isObject(src) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-isArray = Array.isArray || function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Array]";
-};
-
-isFunction = function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Function]";
-};
-
-isObject = function( obj ) {
- return Object.prototype.toString.call( obj ) === "[object Object]";
-};
-
-startsWith = function( value, pattern ) {
- return value.indexOf( pattern ) === 0;
-};
-
-trim = function( value ) {
- return ( value + "" ).replace( regexTrim, "" );
-};
-
-truncate = function( value ) {
- if ( isNaN( value ) ) {
- return NaN;
- }
- return Math[ value < 0 ? "ceil" : "floor" ]( value );
-};
-
-zeroPad = function( str, count, left ) {
- var l;
- for ( l = str.length; l < count; l += 1 ) {
- str = ( left ? ("0" + str) : (str + "0") );
- }
- return str;
-};
-
-//
-// private Globalization utility functions
-//
-
-appendPreOrPostMatch = function( preMatch, strings ) {
- // appends pre- and post- token match strings while removing escaped characters.
- // Returns a single quote count which is used to determine if the token occurs
- // in a string literal.
- var quoteCount = 0,
- escaped = false;
- for ( var i = 0, il = preMatch.length; i < il; i++ ) {
- var c = preMatch.charAt( i );
- switch ( c ) {
- case "\'":
- if ( escaped ) {
- strings.push( "\'" );
- }
- else {
- quoteCount++;
- }
- escaped = false;
- break;
- case "\\":
- if ( escaped ) {
- strings.push( "\\" );
- }
- escaped = !escaped;
- break;
- default:
- strings.push( c );
- escaped = false;
- break;
- }
- }
- return quoteCount;
-};
-
-expandFormat = function( cal, format ) {
- // expands unspecified or single character date formats into the full pattern.
- format = format || "F";
- var pattern,
- patterns = cal.patterns,
- len = format.length;
- if ( len === 1 ) {
- pattern = patterns[ format ];
- if ( !pattern ) {
- throw "Invalid date format string \'" + format + "\'.";
- }
- format = pattern;
- }
- else if ( len === 2 && format.charAt(0) === "%" ) {
- // %X escape format -- intended as a custom format string that is only one character, not a built-in format.
- format = format.charAt( 1 );
- }
- return format;
-};
-
-formatDate = function( value, format, culture ) {
- var cal = culture.calendar,
- convert = cal.convert,
- ret;
-
- if ( !format || !format.length || format === "i" ) {
- if ( culture && culture.name.length ) {
- if ( convert ) {
- // non-gregorian calendar, so we cannot use built-in toLocaleString()
- ret = formatDate( value, cal.patterns.F, culture );
- }
- else {
- var eraDate = new Date( value.getTime() ),
- era = getEra( value, cal.eras );
- eraDate.setFullYear( getEraYear(value, cal, era) );
- ret = eraDate.toLocaleString();
- }
- }
- else {
- ret = value.toString();
- }
- return ret;
- }
-
- var eras = cal.eras,
- sortable = format === "s";
- format = expandFormat( cal, format );
-
- // Start with an empty string
- ret = [];
- var hour,
- zeros = [ "0", "00", "000" ],
- foundDay,
- checkedDay,
- dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
- quoteCount = 0,
- tokenRegExp = getTokenRegExp(),
- converted;
-
- function padZeros( num, c ) {
- var r, s = num + "";
- if ( c > 1 && s.length < c ) {
- r = ( zeros[c - 2] + s);
- return r.substr( r.length - c, c );
- }
- else {
- r = s;
- }
- return r;
- }
-
- function hasDay() {
- if ( foundDay || checkedDay ) {
- return foundDay;
- }
- foundDay = dayPartRegExp.test( format );
- checkedDay = true;
- return foundDay;
- }
-
- function getPart( date, part ) {
- if ( converted ) {
- return converted[ part ];
- }
- switch ( part ) {
- case 0:
- return date.getFullYear();
- case 1:
- return date.getMonth();
- case 2:
- return date.getDate();
- default:
- throw "Invalid part value " + part;
- }
- }
-
- if ( !sortable && convert ) {
- converted = convert.fromGregorian( value );
- }
-
- for ( ; ; ) {
- // Save the current index
- var index = tokenRegExp.lastIndex,
- // Look for the next pattern
- ar = tokenRegExp.exec( format );
-
- // Append the text before the pattern (or the end of the string if not found)
- var preMatch = format.slice( index, ar ? ar.index : format.length );
- quoteCount += appendPreOrPostMatch( preMatch, ret );
-
- if ( !ar ) {
- break;
- }
-
- // do not replace any matches that occur inside a string literal.
- if ( quoteCount % 2 ) {
- ret.push( ar[0] );
- continue;
- }
-
- var current = ar[ 0 ],
- clength = current.length;
-
- switch ( current ) {
- case "ddd":
- //Day of the week, as a three-letter abbreviation
- case "dddd":
- // Day of the week, using the full name
- var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
- ret.push( names[value.getDay()] );
- break;
- case "d":
- // Day of month, without leading zero for single-digit days
- case "dd":
- // Day of month, with leading zero for single-digit days
- foundDay = true;
- ret.push(
- padZeros( getPart(value, 2), clength )
- );
- break;
- case "MMM":
- // Month, as a three-letter abbreviation
- case "MMMM":
- // Month, using the full name
- var part = getPart( value, 1 );
- ret.push(
- ( cal.monthsGenitive && hasDay() ) ?
- ( cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ] ) :
- ( cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ] )
- );
- break;
- case "M":
- // Month, as digits, with no leading zero for single-digit months
- case "MM":
- // Month, as digits, with leading zero for single-digit months
- ret.push(
- padZeros( getPart(value, 1) + 1, clength )
- );
- break;
- case "y":
- // Year, as two digits, but with no leading zero for years less than 10
- case "yy":
- // Year, as two digits, with leading zero for years less than 10
- case "yyyy":
- // Year represented by four full digits
- part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
- if ( clength < 4 ) {
- part = part % 100;
- }
- ret.push(
- padZeros( part, clength )
- );
- break;
- case "h":
- // Hours with no leading zero for single-digit hours, using 12-hour clock
- case "hh":
- // Hours with leading zero for single-digit hours, using 12-hour clock
- hour = value.getHours() % 12;
- if ( hour === 0 ) hour = 12;
- ret.push(
- padZeros( hour, clength )
- );
- break;
- case "H":
- // Hours with no leading zero for single-digit hours, using 24-hour clock
- case "HH":
- // Hours with leading zero for single-digit hours, using 24-hour clock
- ret.push(
- padZeros( value.getHours(), clength )
- );
- break;
- case "m":
- // Minutes with no leading zero for single-digit minutes
- case "mm":
- // Minutes with leading zero for single-digit minutes
- ret.push(
- padZeros( value.getMinutes(), clength )
- );
- break;
- case "s":
- // Seconds with no leading zero for single-digit seconds
- case "ss":
- // Seconds with leading zero for single-digit seconds
- ret.push(
- padZeros( value.getSeconds(), clength )
- );
- break;
- case "t":
- // One character am/pm indicator ("a" or "p")
- case "tt":
- // Multicharacter am/pm indicator
- part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
- ret.push( clength === 1 ? part.charAt(0) : part );
- break;
- case "f":
- // Deciseconds
- case "ff":
- // Centiseconds
- case "fff":
- // Milliseconds
- ret.push(
- padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
- );
- break;
- case "z":
- // Time zone offset, no leading zero
- case "zz":
- // Time zone offset with leading zero
- hour = value.getTimezoneOffset() / 60;
- ret.push(
- ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
- );
- break;
- case "zzz":
- // Time zone offset with leading zero
- hour = value.getTimezoneOffset() / 60;
- ret.push(
- ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 ) +
- // Hard coded ":" separator, rather than using cal.TimeSeparator
- // Repeated here for consistency, plus ":" was already assumed in date parsing.
- ":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
- );
- break;
- case "g":
- case "gg":
- if ( cal.eras ) {
- ret.push(
- cal.eras[ getEra(value, eras) ].name
- );
- }
- break;
- case "/":
- ret.push( cal["/"] );
- break;
- default:
- throw "Invalid date format pattern \'" + current + "\'.";
- }
- }
- return ret.join( "" );
-};
-
-// formatNumber
-(function() {
- var expandNumber;
-
- expandNumber = function( number, precision, formatInfo ) {
- var groupSizes = formatInfo.groupSizes,
- curSize = groupSizes[ 0 ],
- curGroupIndex = 1,
- factor = Math.pow( 10, precision ),
- rounded = Math.round( number * factor ) / factor;
-
- if ( !isFinite(rounded) ) {
- rounded = number;
- }
- number = rounded;
-
- var numberString = number+"",
- right = "",
- split = numberString.split( /e/i ),
- exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
- numberString = split[ 0 ];
- split = numberString.split( "." );
- numberString = split[ 0 ];
- right = split.length > 1 ? split[ 1 ] : "";
-
- if ( exponent > 0 ) {
- right = zeroPad( right, exponent, false );
- numberString += right.slice( 0, exponent );
- right = right.substr( exponent );
- }
- else if ( exponent < 0 ) {
- exponent = -exponent;
- numberString = zeroPad( numberString, exponent + 1, true );
- right = numberString.slice( -exponent, numberString.length ) + right;
- numberString = numberString.slice( 0, -exponent );
- }
-
- if ( precision > 0 ) {
- right = formatInfo[ "." ] +
- ( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
- }
- else {
- right = "";
- }
-
- var stringIndex = numberString.length - 1,
- sep = formatInfo[ "," ],
- ret = "";
-
- while ( stringIndex >= 0 ) {
- if ( curSize === 0 || curSize > stringIndex ) {
- return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
- }
- ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );
-
- stringIndex -= curSize;
-
- if ( curGroupIndex < groupSizes.length ) {
- curSize = groupSizes[ curGroupIndex ];
- curGroupIndex++;
- }
- }
-
- return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
- };
-
- formatNumber = function( value, format, culture ) {
- if ( !isFinite(value) ) {
- if ( value === Infinity ) {
- return culture.numberFormat.positiveInfinity;
- }
- if ( value === -Infinity ) {
- return culture.numberFormat.negativeInfinity;
- }
- return culture.numberFormat.NaN;
- }
- if ( !format || format === "i" ) {
- return culture.name.length ? value.toLocaleString() : value.toString();
- }
- format = format || "D";
-
- var nf = culture.numberFormat,
- number = Math.abs( value ),
- precision = -1,
- pattern;
- if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );
-
- var current = format.charAt( 0 ).toUpperCase(),
- formatInfo;
-
- switch ( current ) {
- case "D":
- pattern = "n";
- number = truncate( number );
- if ( precision !== -1 ) {
- number = zeroPad( "" + number, precision, true );
- }
- if ( value < 0 ) number = "-" + number;
- break;
- case "N":
- formatInfo = nf;
- /* falls through */
- case "C":
- formatInfo = formatInfo || nf.currency;
- /* falls through */
- case "P":
- formatInfo = formatInfo || nf.percent;
- pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
- if ( precision === -1 ) precision = formatInfo.decimals;
- number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
- break;
- default:
- throw "Bad number format specifier: " + current;
- }
-
- var patternParts = /n|\$|-|%/g,
- ret = "";
- for ( ; ; ) {
- var index = patternParts.lastIndex,
- ar = patternParts.exec( pattern );
-
- ret += pattern.slice( index, ar ? ar.index : pattern.length );
-
- if ( !ar ) {
- break;
- }
-
- switch ( ar[0] ) {
- case "n":
- ret += number;
- break;
- case "$":
- ret += nf.currency.symbol;
- break;
- case "-":
- // don't make 0 negative
- if ( /[1-9]/.test(number) ) {
- ret += nf[ "-" ];
- }
- break;
- case "%":
- ret += nf.percent.symbol;
- break;
- }
- }
-
- return ret;
- };
-
-}());
-
-getTokenRegExp = function() {
- // regular expression for matching date and time tokens in format strings.
- return (/\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g);
-};
-
-getEra = function( date, eras ) {
- if ( !eras ) return 0;
- var start, ticks = date.getTime();
- for ( var i = 0, l = eras.length; i < l; i++ ) {
- start = eras[ i ].start;
- if ( start === null || ticks >= start ) {
- return i;
- }
- }
- return 0;
-};
-
-getEraYear = function( date, cal, era, sortable ) {
- var year = date.getFullYear();
- if ( !sortable && cal.eras ) {
- // convert normal gregorian year to era-shifted gregorian
- // year by subtracting the era offset
- year -= cal.eras[ era ].offset;
- }
- return year;
-};
-
-// parseExact
-(function() {
- var expandYear,
- getDayIndex,
- getMonthIndex,
- getParseRegExp,
- outOfRange,
- toUpper,
- toUpperArray;
-
- expandYear = function( cal, year ) {
- // expands 2-digit year into 4 digits.
- if ( year < 100 ) {
- var now = new Date(),
- era = getEra( now ),
- curr = getEraYear( now, cal, era ),
- twoDigitYearMax = cal.twoDigitYearMax;
- twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
- year += curr - ( curr % 100 );
- if ( year > twoDigitYearMax ) {
- year -= 100;
- }
- }
- return year;
- };
-
- getDayIndex = function ( cal, value, abbr ) {
- var ret,
- days = cal.days,
- upperDays = cal._upperDays;
- if ( !upperDays ) {
- cal._upperDays = upperDays = [
- toUpperArray( days.names ),
- toUpperArray( days.namesAbbr ),
- toUpperArray( days.namesShort )
- ];
- }
- value = toUpper( value );
- if ( abbr ) {
- ret = arrayIndexOf( upperDays[1], value );
- if ( ret === -1 ) {
- ret = arrayIndexOf( upperDays[2], value );
- }
- }
- else {
- ret = arrayIndexOf( upperDays[0], value );
- }
- return ret;
- };
-
- getMonthIndex = function( cal, value, abbr ) {
- var months = cal.months,
- monthsGen = cal.monthsGenitive || cal.months,
- upperMonths = cal._upperMonths,
- upperMonthsGen = cal._upperMonthsGen;
- if ( !upperMonths ) {
- cal._upperMonths = upperMonths = [
- toUpperArray( months.names ),
- toUpperArray( months.namesAbbr )
- ];
- cal._upperMonthsGen = upperMonthsGen = [
- toUpperArray( monthsGen.names ),
- toUpperArray( monthsGen.namesAbbr )
- ];
- }
- value = toUpper( value );
- var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
- if ( i < 0 ) {
- i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
- }
- return i;
- };
-
- getParseRegExp = function( cal, format ) {
- // converts a format string into a regular expression with groups that
- // can be used to extract date fields from a date string.
- // check for a cached parse regex.
- var re = cal._parseRegExp;
- if ( !re ) {
- cal._parseRegExp = re = {};
- }
- else {
- var reFormat = re[ format ];
- if ( reFormat ) {
- return reFormat;
- }
- }
-
- // expand single digit formats, then escape regular expression characters.
- var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
- regexp = [ "^" ],
- groups = [],
- index = 0,
- quoteCount = 0,
- tokenRegExp = getTokenRegExp(),
- match;
-
- // iterate through each date token found.
- while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
- var preMatch = expFormat.slice( index, match.index );
- index = tokenRegExp.lastIndex;
-
- // don't replace any matches that occur inside a string literal.
- quoteCount += appendPreOrPostMatch( preMatch, regexp );
- if ( quoteCount % 2 ) {
- regexp.push( match[0] );
- continue;
- }
-
- // add a regex group for the token.
- var m = match[ 0 ],
- len = m.length,
- add;
- switch ( m ) {
- case "dddd": case "ddd":
- case "MMMM": case "MMM":
- case "gg": case "g":
- add = "(\\D+)";
- break;
- case "tt": case "t":
- add = "(\\D*)";
- break;
- case "yyyy":
- case "fff":
- case "ff":
- case "f":
- add = "(\\d{" + len + "})";
- break;
- case "dd": case "d":
- case "MM": case "M":
- case "yy": case "y":
- case "HH": case "H":
- case "hh": case "h":
- case "mm": case "m":
- case "ss": case "s":
- add = "(\\d\\d?)";
- break;
- case "zzz":
- add = "([+-]?\\d\\d?:\\d{2})";
- break;
- case "zz": case "z":
- add = "([+-]?\\d\\d?)";
- break;
- case "/":
- add = "(\\/)";
- break;
- default:
- throw "Invalid date format pattern \'" + m + "\'.";
- }
- if ( add ) {
- regexp.push( add );
- }
- groups.push( match[0] );
- }
- appendPreOrPostMatch( expFormat.slice(index), regexp );
- regexp.push( "$" );
-
- // allow whitespace to differ when matching formats.
- var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
- parseRegExp = { "regExp": regexpStr, "groups": groups };
-
- // cache the regex for this format.
- return re[ format ] = parseRegExp;
- };
-
- outOfRange = function( value, low, high ) {
- return value < low || value > high;
- };
-
- toUpper = function( value ) {
- // "he-IL" has non-breaking space in weekday names.
- return value.split( "\u00A0" ).join( " " ).toUpperCase();
- };
-
- toUpperArray = function( arr ) {
- var results = [];
- for ( var i = 0, l = arr.length; i < l; i++ ) {
- results[ i ] = toUpper( arr[i] );
- }
- return results;
- };
-
- parseExact = function( value, format, culture ) {
- // try to parse the date string by matching against the format string
- // while using the specified culture for date field names.
- value = trim( value );
- var cal = culture.calendar,
- // convert date formats into regular expressions with groupings.
- // use the regexp to determine the input format and extract the date fields.
- parseInfo = getParseRegExp( cal, format ),
- match = new RegExp( parseInfo.regExp ).exec( value );
- if ( match === null ) {
- return null;
- }
- // found a date format that matches the input.
- var groups = parseInfo.groups,
- era = null, year = null, month = null, date = null, weekDay = null,
- hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
- pmHour = false;
- // iterate the format groups to extract and set the date fields.
- for ( var j = 0, jl = groups.length; j < jl; j++ ) {
- var matchGroup = match[ j + 1 ];
- if ( matchGroup ) {
- var current = groups[ j ],
- clength = current.length,
- matchInt = parseInt( matchGroup, 10 );
- switch ( current ) {
- case "dd": case "d":
- // Day of month.
- date = matchInt;
- // check that date is generally in valid range, also checking overflow below.
- if ( outOfRange(date, 1, 31) ) return null;
- break;
- case "MMM": case "MMMM":
- month = getMonthIndex( cal, matchGroup, clength === 3 );
- if ( outOfRange(month, 0, 11) ) return null;
- break;
- case "M": case "MM":
- // Month.
- month = matchInt - 1;
- if ( outOfRange(month, 0, 11) ) return null;
- break;
- case "y": case "yy":
- case "yyyy":
- year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
- if ( outOfRange(year, 0, 9999) ) return null;
- break;
- case "h": case "hh":
- // Hours (12-hour clock).
- hour = matchInt;
- if ( hour === 12 ) hour = 0;
- if ( outOfRange(hour, 0, 11) ) return null;
- break;
- case "H": case "HH":
- // Hours (24-hour clock).
- hour = matchInt;
- if ( outOfRange(hour, 0, 23) ) return null;
- break;
- case "m": case "mm":
- // Minutes.
- min = matchInt;
- if ( outOfRange(min, 0, 59) ) return null;
- break;
- case "s": case "ss":
- // Seconds.
- sec = matchInt;
- if ( outOfRange(sec, 0, 59) ) return null;
- break;
- case "tt": case "t":
- // AM/PM designator.
- // see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
- // the AM tokens. If not, fail the parse for this format.
- pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
- if (
- !pmHour && (
- !cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
- )
- ) return null;
- break;
- case "f":
- // Deciseconds.
- case "ff":
- // Centiseconds.
- case "fff":
- // Milliseconds.
- msec = matchInt * Math.pow( 10, 3 - clength );
- if ( outOfRange(msec, 0, 999) ) return null;
- break;
- case "ddd":
- // Day of week.
- case "dddd":
- // Day of week.
- weekDay = getDayIndex( cal, matchGroup, clength === 3 );
- if ( outOfRange(weekDay, 0, 6) ) return null;
- break;
- case "zzz":
- // Time zone offset in +/- hours:min.
- var offsets = matchGroup.split( /:/ );
- if ( offsets.length !== 2 ) return null;
- hourOffset = parseInt( offsets[0], 10 );
- if ( outOfRange(hourOffset, -12, 13) ) return null;
- var minOffset = parseInt( offsets[1], 10 );
- if ( outOfRange(minOffset, 0, 59) ) return null;
- tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
- break;
- case "z": case "zz":
- // Time zone offset in +/- hours.
- hourOffset = matchInt;
- if ( outOfRange(hourOffset, -12, 13) ) return null;
- tzMinOffset = hourOffset * 60;
- break;
- case "g": case "gg":
- var eraName = matchGroup;
- if ( !eraName || !cal.eras ) return null;
- eraName = trim( eraName.toLowerCase() );
- for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
- if ( eraName === cal.eras[i].name.toLowerCase() ) {
- era = i;
- break;
- }
- }
- // could not find an era with that name
- if ( era === null ) return null;
- break;
- }
- }
- }
- var result = new Date(), defaultYear, convert = cal.convert;
- defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
- if ( year === null ) {
- year = defaultYear;
- }
- else if ( cal.eras ) {
- // year must be shifted to normal gregorian year
- // but not if year was not specified, its already normal gregorian
- // per the main if clause above.
- year += cal.eras[( era || 0 )].offset;
- }
- // set default day and month to 1 and January, so if unspecified, these are the defaults
- // instead of the current day/month.
- if ( month === null ) {
- month = 0;
- }
- if ( date === null ) {
- date = 1;
- }
- // now have year, month, and date, but in the culture's calendar.
- // convert to gregorian if necessary
- if ( convert ) {
- result = convert.toGregorian( year, month, date );
- // conversion failed, must be an invalid match
- if ( result === null ) return null;
- }
- else {
- // have to set year, month and date together to avoid overflow based on current date.
- result.setFullYear( year, month, date );
- // check to see if date overflowed for specified month (only checked 1-31 above).
- if ( result.getDate() !== date ) return null;
- // invalid day of week.
- if ( weekDay !== null && result.getDay() !== weekDay ) {
- return null;
- }
- }
- // if pm designator token was found make sure the hours fit the 24-hour clock.
- if ( pmHour && hour < 12 ) {
- hour += 12;
- }
- result.setHours( hour, min, sec, msec );
- if ( tzMinOffset !== null ) {
- // adjust timezone to utc before applying local offset.
- var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
- // Safari limits hours and minutes to the range of -127 to 127. We need to use setHours
- // to ensure both these fields will not exceed this range. adjustedMin will range
- // somewhere between -1440 and 1500, so we only need to split this into hours.
- result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
- }
- return result;
- };
-}());
-
-parseNegativePattern = function( value, nf, negativePattern ) {
- var neg = nf[ "-" ],
- pos = nf[ "+" ],
- ret;
- switch ( negativePattern ) {
- case "n -":
- neg = " " + neg;
- pos = " " + pos;
- /* falls through */
- case "n-":
- if ( endsWith(value, neg) ) {
- ret = [ "-", value.substr(0, value.length - neg.length) ];
- }
- else if ( endsWith(value, pos) ) {
- ret = [ "+", value.substr(0, value.length - pos.length) ];
- }
- break;
- case "- n":
- neg += " ";
- pos += " ";
- /* falls through */
- case "-n":
- if ( startsWith(value, neg) ) {
- ret = [ "-", value.substr(neg.length) ];
- }
- else if ( startsWith(value, pos) ) {
- ret = [ "+", value.substr(pos.length) ];
- }
- break;
- case "(n)":
- if ( startsWith(value, "(") && endsWith(value, ")") ) {
- ret = [ "-", value.substr(1, value.length - 2) ];
- }
- break;
- }
- return ret || [ "", value ];
-};
-
-//
-// public instance functions
-//
-
-Globalize.prototype.findClosestCulture = function( cultureSelector ) {
- return Globalize.findClosestCulture.call( this, cultureSelector );
-};
-
-Globalize.prototype.format = function( value, format, cultureSelector ) {
- return Globalize.format.call( this, value, format, cultureSelector );
-};
-
-Globalize.prototype.localize = function( key, cultureSelector ) {
- return Globalize.localize.call( this, key, cultureSelector );
-};
-
-Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
- return Globalize.parseInt.call( this, value, radix, cultureSelector );
-};
-
-Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
- return Globalize.parseFloat.call( this, value, radix, cultureSelector );
-};
-
-Globalize.prototype.culture = function( cultureSelector ) {
- return Globalize.culture.call( this, cultureSelector );
-};
-
-//
-// public singleton functions
-//
-
-Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {
-
- var base = {},
- isNew = false;
-
- if ( typeof cultureName !== "string" ) {
- // cultureName argument is optional string. If not specified, assume info is first
- // and only argument. Specified info deep-extends current culture.
- info = cultureName;
- cultureName = this.culture().name;
- base = this.cultures[ cultureName ];
- } else if ( typeof baseCultureName !== "string" ) {
- // baseCultureName argument is optional string. If not specified, assume info is second
- // argument. Specified info deep-extends specified culture.
- // If specified culture does not exist, create by deep-extending default
- info = baseCultureName;
- isNew = ( this.cultures[ cultureName ] == null );
- base = this.cultures[ cultureName ] || this.cultures[ "default" ];
- } else {
- // cultureName and baseCultureName specified. Assume a new culture is being created
- // by deep-extending an specified base culture
- isNew = true;
- base = this.cultures[ baseCultureName ];
- }
-
- this.cultures[ cultureName ] = extend(true, {},
- base,
- info
- );
- // Make the standard calendar the current culture if it's a new culture
- if ( isNew ) {
- this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
- }
-};
-
-Globalize.findClosestCulture = function( name ) {
- var match;
- if ( !name ) {
- return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
- }
- if ( typeof name === "string" ) {
- name = name.split( "," );
- }
- if ( isArray(name) ) {
- var lang,
- cultures = this.cultures,
- list = name,
- i, l = list.length,
- prioritized = [];
- for ( i = 0; i < l; i++ ) {
- name = trim( list[i] );
- var pri, parts = name.split( ";" );
- lang = trim( parts[0] );
- if ( parts.length === 1 ) {
- pri = 1;
- }
- else {
- name = trim( parts[1] );
- if ( name.indexOf("q=") === 0 ) {
- name = name.substr( 2 );
- pri = parseFloat( name );
- pri = isNaN( pri ) ? 0 : pri;
- }
- else {
- pri = 1;
- }
- }
- prioritized.push({ lang: lang, pri: pri });
- }
- prioritized.sort(function( a, b ) {
- if ( a.pri < b.pri ) {
- return 1;
- } else if ( a.pri > b.pri ) {
- return -1;
- }
- return 0;
- });
- // exact match
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- match = cultures[ lang ];
- if ( match ) {
- return match;
- }
- }
-
- // neutral language match
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- do {
- var index = lang.lastIndexOf( "-" );
- if ( index === -1 ) {
- break;
- }
- // strip off the last part. e.g. en-US => en
- lang = lang.substr( 0, index );
- match = cultures[ lang ];
- if ( match ) {
- return match;
- }
- }
- while ( 1 );
- }
-
- // last resort: match first culture using that language
- for ( i = 0; i < l; i++ ) {
- lang = prioritized[ i ].lang;
- for ( var cultureKey in cultures ) {
- var culture = cultures[ cultureKey ];
- if ( culture.language === lang ) {
- return culture;
- }
- }
- }
- }
- else if ( typeof name === "object" ) {
- return name;
- }
- return match || null;
-};
-
-Globalize.format = function( value, format, cultureSelector ) {
- var culture = this.findClosestCulture( cultureSelector );
- if ( value instanceof Date ) {
- value = formatDate( value, format, culture );
- }
- else if ( typeof value === "number" ) {
- value = formatNumber( value, format, culture );
- }
- return value;
-};
-
-Globalize.localize = function( key, cultureSelector ) {
- return this.findClosestCulture( cultureSelector ).messages[ key ] ||
- this.cultures[ "default" ].messages[ key ];
-};
-
-Globalize.parseDate = function( value, formats, culture ) {
- culture = this.findClosestCulture( culture );
-
- var date, prop, patterns;
- if ( formats ) {
- if ( typeof formats === "string" ) {
- formats = [ formats ];
- }
- if ( formats.length ) {
- for ( var i = 0, l = formats.length; i < l; i++ ) {
- var format = formats[ i ];
- if ( format ) {
- date = parseExact( value, format, culture );
- if ( date ) {
- break;
- }
- }
- }
- }
- } else {
- patterns = culture.calendar.patterns;
- for ( prop in patterns ) {
- date = parseExact( value, patterns[prop], culture );
- if ( date ) {
- break;
- }
- }
- }
-
- return date || null;
-};
-
-Globalize.parseInt = function( value, radix, cultureSelector ) {
- return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
-};
-
-Globalize.parseFloat = function( value, radix, cultureSelector ) {
- // radix argument is optional
- if ( typeof radix !== "number" ) {
- cultureSelector = radix;
- radix = 10;
- }
-
- var culture = this.findClosestCulture( cultureSelector );
- var ret = NaN,
- nf = culture.numberFormat;
-
- if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
- // remove currency symbol
- value = value.replace( culture.numberFormat.currency.symbol, "" );
- // replace decimal seperator
- value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
- }
-
- //Remove percentage character from number string before parsing
- if ( value.indexOf(culture.numberFormat.percent.symbol) > -1){
- value = value.replace( culture.numberFormat.percent.symbol, "" );
- }
-
- // remove spaces: leading, trailing and between - and number. Used for negative currency pt-BR
- value = value.replace( / /g, "" );
-
- // allow infinity or hexidecimal
- if ( regexInfinity.test(value) ) {
- ret = parseFloat( value );
- }
- else if ( !radix && regexHex.test(value) ) {
- ret = parseInt( value, 16 );
- }
- else {
-
- // determine sign and number
- var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
- sign = signInfo[ 0 ],
- num = signInfo[ 1 ];
-
- // #44 - try parsing as "(n)"
- if ( sign === "" && nf.pattern[0] !== "(n)" ) {
- signInfo = parseNegativePattern( value, nf, "(n)" );
- sign = signInfo[ 0 ];
- num = signInfo[ 1 ];
- }
-
- // try parsing as "-n"
- if ( sign === "" && nf.pattern[0] !== "-n" ) {
- signInfo = parseNegativePattern( value, nf, "-n" );
- sign = signInfo[ 0 ];
- num = signInfo[ 1 ];
- }
-
- sign = sign || "+";
-
- // determine exponent and number
- var exponent,
- intAndFraction,
- exponentPos = num.indexOf( "e" );
- if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
- if ( exponentPos < 0 ) {
- intAndFraction = num;
- exponent = null;
- }
- else {
- intAndFraction = num.substr( 0, exponentPos );
- exponent = num.substr( exponentPos + 1 );
- }
- // determine decimal position
- var integer,
- fraction,
- decSep = nf[ "." ],
- decimalPos = intAndFraction.indexOf( decSep );
- if ( decimalPos < 0 ) {
- integer = intAndFraction;
- fraction = null;
- }
- else {
- integer = intAndFraction.substr( 0, decimalPos );
- fraction = intAndFraction.substr( decimalPos + decSep.length );
- }
- // handle groups (e.g. 1,000,000)
- var groupSep = nf[ "," ];
- integer = integer.split( groupSep ).join( "" );
- var altGroupSep = groupSep.replace( /\u00A0/g, " " );
- if ( groupSep !== altGroupSep ) {
- integer = integer.split( altGroupSep ).join( "" );
- }
- // build a natively parsable number string
- var p = sign + integer;
- if ( fraction !== null ) {
- p += "." + fraction;
- }
- if ( exponent !== null ) {
- // exponent itself may have a number patternd
- var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
- p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
- }
- if ( regexParseFloat.test(p) ) {
- ret = parseFloat( p );
- }
- }
- return ret;
-};
-
-Globalize.culture = function( cultureSelector ) {
- // setter
- if ( typeof cultureSelector !== "undefined" ) {
- this.cultureSelector = cultureSelector;
- }
- // getter
- return this.findClosestCulture( cultureSelector ) || this.cultures[ "default" ];
-};
-
-}( this )); \ No newline at end of file
diff --git a/apps/it/static/js/ui/external/jquery.mousewheel.js b/apps/it/static/js/ui/external/jquery.mousewheel.js
deleted file mode 100644
index 8c60304..0000000
--- a/apps/it/static/js/ui/external/jquery.mousewheel.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
- * Licensed under the MIT License (LICENSE.txt).
- *
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
- * Thanks to: Seamus Leahy for adding deltaX and deltaY
- *
- * Version: 3.1.0
- *
- * Requires: 1.2.2+
- */
-
-(function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else {
- // Browser globals
- factory(jQuery);
- }
-}(function ($) {
-
- var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll'];
- var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
- var lowestDelta, lowestDeltaXY;
-
- if ($.event.fixHooks) {
- for ( var i=toFix.length; i; ) {
- $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
- }
- }
-
- $.event.special.mousewheel = {
- setup: function() {
- if ( this.addEventListener ) {
- for ( var i=toBind.length; i; ) {
- this.addEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = handler;
- }
- },
-
- teardown: function() {
- if ( this.removeEventListener ) {
- for ( var i=toBind.length; i; ) {
- this.removeEventListener( toBind[--i], handler, false );
- }
- } else {
- this.onmousewheel = null;
- }
- }
- };
-
- $.fn.extend({
- mousewheel: function(fn) {
- return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
- },
-
- unmousewheel: function(fn) {
- return this.unbind("mousewheel", fn);
- }
- });
-
-
- function handler(event) {
- var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, deltaX = 0, deltaY = 0, absDelta = 0, absDeltaXY = 0;
- event = $.event.fix(orgEvent);
- event.type = "mousewheel";
-
- // Old school scrollwheel delta
- if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
- if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
-
- // New school wheel delta (wheel event)
- if ( orgEvent.deltaY ) {
- deltaY = orgEvent.deltaY * -1;
- delta = deltaY;
- }
- if ( orgEvent.deltaX ) {
- deltaX = orgEvent.deltaX;
- delta = deltaX * -1;
- }
-
- // Webkit
- if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
- if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
-
- absDelta = Math.abs(delta);
- if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
-
- absDeltaXY = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
- if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
-
- // Add event and delta to the front of the arguments
- args.unshift(event, Math.floor(delta/lowestDelta), Math.floor(deltaX/lowestDeltaXY), Math.floor(deltaY/lowestDeltaXY));
-
- return ($.event.dispatch || $.event.handle).apply(this, args);
- }
-
-}));
diff --git a/apps/it/static/js/ui/external/jshint.js b/apps/it/static/js/ui/external/jshint.js
deleted file mode 100644
index 8f06d9b..0000000
--- a/apps/it/static/js/ui/external/jshint.js
+++ /dev/null
@@ -1,4835 +0,0 @@
-/*!
- * JSHint, by JSHint Community.
- *
- * This file (and this file only) is 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 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 1) at which the lint was found
- character : The character (relative to 1) 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 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,
- character: NUMBER,
- last: NUMBER,
- lastcharacter: NUMBER,
- param: [
- STRING
- ],
- closure: [
- STRING
- ],
- var: [
- STRING
- ],
- exception: [
- STRING
- ],
- outer: [
- STRING
- ],
- unused: [
- STRING
- ],
- global: [
- STRING
- ],
- label: [
- STRING
- ]
- ],
- globals: [
- STRING
- ],
- member: {
- STRING: NUMBER
- },
- unused: [
- {
- 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,
- undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true
-*/
-
-/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
- "(breakage)", "(character)", "(context)", "(error)", "(explicitNewcap)", "(global)",
- "(identifier)", "(last)", "(lastcharacter)", "(line)", "(loopage)", "(metrics)",
- "(name)", "(onevar)", "(params)", "(scope)", "(statement)", "(verb)", "(tokens)", "(catch)",
- "*", "+", "++", "-", "--", "\/", "<", "<=", "==",
- "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
- __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,
- Autocompleter, Asset, Boolean, Builder, Buffer, Browser, Blob, COM, CScript, Canvas,
- CustomAnimation, Class, Control, ComplexityCount, Chain, Color, Cookie, Core, DataView, Date,
- Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMEvent, DOMReady, DOMParser,
- Drag, E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
- Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
- FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,
- HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,
- HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,
- HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,
- HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,
- HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,
- HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,
- HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,
- HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,
- HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,
- HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,
- HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,
- HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,
- HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,
- HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,
- Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array,
- Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
- MAX_VALUE, MIN_VALUE, Map, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,
- MoveAnimation, MooTools, MutationObserver, NaN, Native, NEGATIVE_INFINITY, Node, NodeFilter,
- Number, Object, ObjectRange,
- Option, Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,
- RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, Set,
- SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
- ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
- Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,
- SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
- Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,
- VBArray, WeakMap, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,
- XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,
- "\\", a, abs, addEventListener, address, alert, apply, applicationCache, arguments, arity,
- asi, atob, b, basic, basicToken, bitwise, blacklist, block, blur, boolOptions, boss,
- browser, btoa, c, call, callee, caller, camelcase, cases, charAt, charCodeAt, character,
- clearInterval, clearTimeout, close, closed, closure, comment, complexityCount, 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, else, emit, encodeURI, encodeURIComponent, elem,
- eqeq, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
- ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, forEach,
- forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
- g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
- hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
- indent, indexOf, init, ins, internals, instanceOf, isAlpha, isApplicationRunning, isArray,
- isDigit, isFinite, isNaN, iterator, java, join, jshint,
- JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastcharacter, lastsemic, laxbreak,
- laxcomma, latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
- log, loopfunc, m, match, max, maxcomplexity, maxdepth, maxerr, maxlen, maxstatements, maxparams,
- member, message, meta, module, moveBy, moveTo, mootools, multistr, name, navigator, new, newcap,
- nestedBlockDepth, noarg, node, noempty, nomen, nonew, nonstandard, nud, onbeforeunload, onblur,
- onerror, onevar, onecase, onfocus, onload, onresize, onunload, open, openDatabase, openURL,
- opener, opera, options, outer, param, parent, parseFloat, parseInt, passfail, plusplus,
- postMessage, pop, predef, print, process, prompt, proto, prototype, prototypejs, provides, push,
- quit, quotmark, range, raw, reach, reason, regexp, readFile, readUrl, regexdash,
- removeEventListener, replace, report, require, reserved, resizeBy, resizeTo, resolvePath,
- resumeUpdates, respond, rhino, right, runCommand, scroll, scope, screen, scripturl, scrollBy,
- scrollTo, scrollbar, search, seal, self, send, serialize, sessionStorage, setInterval, setTimeout,
- setter, setterToken, shift, slice, smarttabs, sort, spawn, split, statement, statementCount, stack,
- status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync, test, toLowerCase,
- toString, toUpperCase, toint32, token, tokens, top, trailing, type, typeOf, Uint16Array,
- Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis, value, valueOf, var, vars,
- version, verifyMaxParametersPerFunction, verifyMaxStatementsPerFunction,
- verifyMaxComplexityPerFunction, verifyMaxNestedBlockDepthPerFunction, WebSocket, withstmt, white,
- window, windows, Worker, worker, wsh, yui, YUI, Y, YUI_config*/
-
-/*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
- camelcase : true, // if identifiers should be required in camel case
- couch : true, // if CouchDB globals should be predefined
- curly : true, // if curly braces around all blocks should be required
- 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
- esnext : true, // if es.next specific 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
- funcscope : true, // if only function scope should be used for scope tests
- globalstrict: true, // if global "use strict"; should be allowed (also
- // enables 'strict')
- immed : true, // if immediate invocations must be wrapped in parens
- iterator : true, // if the `__iterator__` property should be allowed
- jquery : true, // if jQuery globals should be predefined
- lastsemic : true, // if semicolons may be ommitted for the trailing
- // statements inside of a one-line blocks.
- latedef : true, // if the use before definition should not be tolerated
- laxbreak : true, // if line breaks should not be checked
- laxcomma : true, // if line breaks should not be checked around commas
- loopfunc : true, // if functions should be allowed to be defined within
- // loops
- mootools : true, // if MooTools globals should be predefined
- multistr : true, // allow multiline strings
- 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
- nonstandard : true, // if non-standard (but widely adopted) globals should
- // be predefined
- nomen : true, // if names should be checked
- onevar : true, // if only one var statement per function should be
- // allowed
- onecase : true, // if one case switch statements should be allowed
- passfail : true, // if the scan should stop on first error
- plusplus : true, // if increment/decrement should not be allowed
- proto : true, // if the `__proto__` property should be allowed
- prototypejs : true, // if Prototype and Scriptaculous globals should be
- // predefined
- regexdash : true, // if unescaped first/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
- unused : true, // if variables should be always used
- scripturl : true, // if script-targeted URLs should be tolerated
- shadow : true, // if variable shadowing should be tolerated
- smarttabs : true, // if smarttabs should be tolerated
- // (http://www.emacswiki.org/emacs/SmartTabs)
- 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
- validthis : true, // if 'this' inside a non-constructor function is valid.
- // This is a function scoped option only.
- withstmt : true, // if with statements should be allowed
- white : true, // if strict whitespace rules apply
- worker : true, // if Web Worker script symbols should be allowed
- wsh : true, // if the Windows Scripting Host environment globals
- // should be predefined
- yui : true // YUI variables should be predefined
- },
-
- // These are the JSHint options that can take any value
- // (we use this object to detect invalid options)
- valOptions = {
- maxlen : false,
- indent : false,
- maxerr : false,
- predef : false,
- quotmark : false, //'single'|'double'|true
- scope : false,
- maxstatements: false, // {int} max statements per function
- maxdepth : false, // {int} max nested block depth per function
- maxparams : false, // {int} max params per function
- maxcomplexity: false // {int} max cyclomatic complexity per function
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the definition in JSHint is opposite JSLint
- invertedOptions = {
- bitwise : true,
- forin : true,
- newcap : true,
- nomen : true,
- plusplus : true,
- regexp : true,
- undef : true,
- white : true,
-
- // Inverted and renamed, use JSHint name here
- eqeqeq : true,
- onevar : true
- },
-
- // These are JSHint boolean options which are shared with JSLint
- // where the name has been changed but the effect is unchanged
- renamedOptions = {
- eqeq : "eqeqeq",
- vars : "onevar",
- windows : "wsh"
- },
-
-
- // browser contains a set of global names which are commonly provided by a
- // web browser environment.
- browser = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- DataView : false,
- DOMParser : false,
- defaultStatus : false,
- document : false,
- event : false,
- FileReader : false,
- Float32Array : false,
- Float64Array : false,
- FormData : false,
- focus : false,
- frames : false,
- getComputedStyle : false,
- HTMLElement : false,
- HTMLAnchorElement : false,
- HTMLBaseElement : false,
- HTMLBlockquoteElement : false,
- HTMLBodyElement : false,
- HTMLBRElement : false,
- HTMLButtonElement : false,
- HTMLCanvasElement : false,
- HTMLDirectoryElement : false,
- HTMLDivElement : false,
- HTMLDListElement : false,
- HTMLFieldSetElement : false,
- HTMLFontElement : false,
- HTMLFormElement : false,
- HTMLFrameElement : false,
- HTMLFrameSetElement : false,
- HTMLHeadElement : false,
- HTMLHeadingElement : false,
- HTMLHRElement : false,
- HTMLHtmlElement : false,
- HTMLIFrameElement : false,
- HTMLImageElement : false,
- HTMLInputElement : false,
- HTMLIsIndexElement : false,
- HTMLLabelElement : false,
- HTMLLayerElement : false,
- HTMLLegendElement : false,
- HTMLLIElement : false,
- HTMLLinkElement : false,
- HTMLMapElement : false,
- HTMLMenuElement : false,
- HTMLMetaElement : false,
- HTMLModElement : false,
- HTMLObjectElement : false,
- HTMLOListElement : false,
- HTMLOptGroupElement : false,
- HTMLOptionElement : false,
- HTMLParagraphElement : false,
- HTMLParamElement : false,
- HTMLPreElement : false,
- HTMLQuoteElement : false,
- HTMLScriptElement : false,
- HTMLSelectElement : false,
- HTMLStyleElement : false,
- HTMLTableCaptionElement : false,
- HTMLTableCellElement : false,
- HTMLTableColElement : false,
- HTMLTableElement : false,
- HTMLTableRowElement : false,
- HTMLTableSectionElement : false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Image : false,
- length : false,
- localStorage : false,
- location : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : 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,
- sessionStorage : false,
- setInterval : false,
- setTimeout : false,
- SharedWorker : false,
- status : false,
- top : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XMLHttpRequest : false,
- XMLSerializer : 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,
- provides : false
- },
-
- declared, // Globals that were declared using /*global ... */ syntax.
-
- devel = {
- alert : false,
- confirm : false,
- console : false,
- Debug : false,
- opera : false,
- prompt : false
- },
-
- dojo = {
- dojo : false,
- dijit : false,
- dojox : false,
- define : false,
- "require" : false
- },
-
- 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,
- Asset : false,
- Browser : false,
- Chain : false,
- Class : false,
- Color : false,
- Cookie : false,
- Core : false,
- Document : false,
- DomReady : false,
- DOMEvent : 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,
- Buffer : false,
- console : false,
- exports : true, // In Node it is ok to exports = module.exports = foo();
- GLOBAL : false,
- global : false,
- module : false,
- process : false,
- require : false,
- setTimeout : false,
- clearTimeout : false,
- setInterval : false,
- clearInterval : 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
- },
-
- quotmark,
-
- 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
- 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,
- Map : false,
- Math : false,
- NaN : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- Set : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false,
- WeakMap : false
- },
-
- // widely adopted global names that are not part of ECMAScript standard
- nonstandard = {
- escape : false,
- unescape : false
- },
-
- directive,
- syntax = {},
- tab,
- token,
- unuseds,
- urls,
- useESNextSyntax,
- warnings,
-
- worker = {
- importScripts : true,
- postMessage : true,
- self : true
- },
-
- wsh = {
- ActiveXObject : true,
- Enumerator : true,
- GetObject : true,
- ScriptEngine : true,
- ScriptEngineBuildVersion : true,
- ScriptEngineMajorVersion : true,
- ScriptEngineMinorVersion : true,
- VBArray : true,
- WSH : true,
- WScript : true,
- XDomainRequest : true
- },
-
- yui = {
- YUI : false,
- Y : false,
- YUI_config : false
- };
- // Regular expressions. Some of these are stupidly long.
- var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
- (function () {
- /*jshint maxlen:300 */
-
- // unsafe comment or string
- ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/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*([(){}\[.,:;'"~\?\]#@]|==?=?|\/=(?!(\S*\/[gim]?))|\/(\*(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);
- }
-
- function checkOption(name, t) {
- if (valOptions[name] === undefined && boolOptions[name] === undefined) {
- warning("Bad option: '" + name + "'.", t);
- }
- }
-
- function isString(obj) {
- return Object.prototype.toString.call(obj) === "[object String]";
- }
-
- // Provide critical ES5 functions to ES3.
-
- if (typeof Array.isArray !== "function") {
- Array.isArray = function (o) {
- return Object.prototype.toString.apply(o) === "[object Array]";
- };
- }
-
- if (!Array.prototype.forEach) {
- Array.prototype.forEach = function (fn, scope) {
- var len = this.length;
-
- for (var i = 0; i < len; i++) {
- fn.call(scope || this, this[i], i, this);
- }
- };
- }
-
- if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
- if (this === null || this === undefined) {
- throw new TypeError();
- }
-
- var t = new Object(this);
- var len = t.length >>> 0;
-
- if (len === 0) {
- return -1;
- }
-
- var n = 0;
- if (arguments.length > 0) {
- n = Number(arguments[1]);
- if (n != n) { // shortcut for verifying if it's NaN
- n = 0;
- } else if (n !== 0 && n != Infinity && n != -Infinity) {
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
- }
- }
-
- if (n >= len) {
- return -1;
- }
-
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
- for (; k < len; k++) {
- if (k in t && t[k] === searchElement) {
- return k;
- }
- }
-
- return -1;
- };
- }
-
- 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
-
- function isAlpha(str) {
- return (str >= "a" && str <= "z\uffff") ||
- (str >= "A" && str <= "Z\uffff");
- }
-
- function isDigit(str) {
- return (str >= "0" && str <= "9");
- }
-
- function isIdentifier(token, value) {
- if (!token)
- return false;
-
- if (!token.identifier || token.value !== value)
- return false;
-
- return true;
- }
-
- function supplant(str, data) {
- return str.replace(/\{([^{}]*)\}/g, function (a, b) {
- var r = data[b];
- return typeof r === "string" || typeof r === "number" ? r : a;
- });
- }
-
- function combine(t, o) {
- var n;
- for (n in o) {
- if (is_own(o, n) && !is_own(JSHINT.blacklist, n)) {
- t[n] = o[n];
- }
- }
- }
-
- function updatePredefined() {
- Object.keys(JSHINT.blacklist).forEach(function (key) {
- delete predefined[key];
- });
- }
-
- 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);
- option.globalstrict = true;
- }
-
- if (option.devel) {
- combine(predefined, devel);
- }
-
- if (option.dojo) {
- combine(predefined, dojo);
- }
-
- if (option.browser) {
- combine(predefined, browser);
- }
-
- if (option.nonstandard) {
- combine(predefined, nonstandard);
- }
-
- if (option.jquery) {
- combine(predefined, jquery);
- }
-
- if (option.mootools) {
- combine(predefined, mootools);
- }
-
- if (option.worker) {
- combine(predefined, worker);
- }
-
- if (option.wsh) {
- combine(predefined, wsh);
- }
-
- if (option.esnext) {
- useESNextSyntax();
- }
-
- if (option.globalstrict && option.strict !== false) {
- option.strict = true;
- }
-
- if (option.yui) {
- combine(predefined, yui);
- }
- }
-
-
- // 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).",
- raw: message
- };
- }
-
- function isundef(scope, m, t, a) {
- return JSHINT.undefs.push([scope, m, t, a]);
- }
-
- 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,
- scope: JSHINT.scope,
- a: a,
- b: b,
- c: c,
- d: d
- };
- w.reason = supplant(m, 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) {
- warning(m, t, a, b, c, d);
- }
-
- function errorAt(m, l, ch, a, b, c, d) {
- return error(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
-
- // Tracking of "internal" scripts, like eval containing a static string
- function addInternalSrc(elem, src) {
- var i;
- i = {
- id: "(internal)",
- elem: elem,
- value: src
- };
- JSHINT.internals.push(i);
- return i;
- }
-
-
-// lexical analysis and token construction
-
- var lex = (function lex() {
- var character, from, line, s;
-
-// Private lex methods
-
- function nextLine() {
- var at,
- match,
- tw; // trailing whitespace check
-
- if (line >= lines.length)
- return false;
-
- character = 1;
- s = lines[line];
- line += 1;
-
- // If smarttabs option is used check for spaces followed by tabs only.
- // Otherwise check for any occurence of mixed tabs and spaces.
- // Tabs and one space followed by block comment is allowed.
- if (option.smarttabs) {
- // negative look-behind for "//"
- match = s.match(/(\/\/)? \t/);
- at = match && !match[1] ? 0 : -1;
- } else {
- at = s.search(/ \t|\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 = option.trailing && s.match(/^(.*?)\s+$/);
- if (tw && !/^\s+$/.test(s)) {
- warningAt("Trailing whitespace.", line, tw[1].length + 1);
- }
- return true;
- }
-
-// Produce a token object. The token inherits from a syntax symbol.
-
- function it(type, value) {
- var i, t;
-
- function checkName(name) {
- if (!option.proto && name === "__proto__") {
- warningAt("The '{a}' property is deprecated.", line, from, name);
- return;
- }
-
- if (!option.iterator && name === "__iterator__") {
- warningAt("'{a}' is only available in JavaScript 1.7.", line, from, name);
- return;
- }
-
- // Check for dangling underscores unless we're in Node
- // environment and this identifier represents built-in
- // Node globals with underscores.
-
- var hasDangling = /^(_+.*|.*_+)$/.test(name);
-
- if (option.nomen && hasDangling && name !== "_") {
- if (option.node && token.id !== "." && /^(__dirname|__filename)$/.test(name))
- return;
-
- warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", name);
- return;
- }
-
- // Check for non-camelcase names. Names like MY_VAR and
- // _myVar are okay though.
-
- if (option.camelcase) {
- if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) {
- warningAt("Identifier '{a}' is not in camel case.", line, from, value);
- }
- }
- }
-
- 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;
- checkName(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" ||
- i === "case");
- }
- 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, isLiteral, isInRange, n;
-
- 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 = "", allowNewLine = false;
-
- if (jsonmode && x !== "\"") {
- warningAt("Strings must use doublequote.",
- line, character);
- }
-
- if (option.quotmark) {
- if (option.quotmark === "single" && x !== "'") {
- warningAt("Strings must use singlequote.",
- line, character);
- } else if (option.quotmark === "double" && x !== "\"") {
- warningAt("Strings must use doublequote.",
- line, character);
- } else if (option.quotmark === true) {
- quotmark = quotmark || x;
- if (quotmark !== x) {
- warningAt("Mixed double and single quotes.",
- 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;
-
-unclosedString:
- for (;;) {
- while (j >= s.length) {
- j = 0;
-
- var cl = line, cf = from;
- if (!nextLine()) {
- errorAt("Unclosed string.", cl, cf);
- break unclosedString;
- }
-
- if (allowNewLine) {
- allowNewLine = false;
- } else {
- warningAt("Unclosed string.", cl, cf);
- }
- }
-
- 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);
- n = s.charAt(j + 1);
- 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 "0":
- c = "\0";
- // Octal literals fail in strict mode
- // check if the number is between 00 and 07
- // where 'n' is the token next to 'c'
- if (n >= 0 && n <= 7 && directive["use strict"]) {
- warningAt(
- "Octal literals are not allowed in strict mode.",
- line, character);
- }
- 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;
- case "":
- // last character is escape character
- // always allow new line if escaped, but show
- // warning if option is not set
- allowNewLine = true;
- if (option.multistr) {
- if (jsonmode) {
- warningAt("Avoid EOL escapement.", line, character);
- }
- c = "";
- character -= 1;
- break;
- }
- warningAt("Bad escapement of EOL. Use option multistr if needed.",
- line, character);
- break;
- case "!":
- if (s.charAt(j - 2) === "<")
- break;
- /*falls through*/
- 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));
- s = "";
- }
- } else {
-
- // identifier
-
- if (isAlpha(c) || c === "_" || c === "$") {
- return it("(identifier)", t);
- }
-
- // number
-
- if (isDigit(c)) {
- if (!isFinite(Number(t))) {
- warningAt("Bad number '{a}'.",
- line, character, t);
- }
- if (isAlpha(s.substr(0, 1))) {
- warningAt("Missing space after '{a}'.",
- line, character, t);
- }
- if (c === "0") {
- d = t.substr(1, 1);
- if (isDigit(d)) {
- 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 "//":
- s = "";
- token.comment = true;
- break;
-
- // /* comment
-
- case "/*":
- for (;;) {
- i = s.search(lx);
- if (i >= 0) {
- break;
- }
- if (!nextLine()) {
- errorAt("Unclosed 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 (s.charAt(0) === "=") {
- 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 quit("Stopping.", line, from);
- case "/":
- if (depth > 0) {
- warningAt("{a} unterminated regular expression " +
- "group(s).", line, from + l, depth);
- }
- 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 (s.charAt(l) === "]") {
- errorAt("Unescaped '{a}'.",
- line, from + l, "^");
- }
- }
- if (c === "]") {
- warningAt("Empty class.", line,
- from + l - 1);
- }
- isLiteral = false;
- isInRange = false;
-klass:
- do {
- c = s.charAt(l);
- l += 1;
- switch (c) {
- case "[":
- case "^":
- warningAt("Unescaped '{a}'.",
- line, from + l, c);
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "-":
- if (isLiteral && !isInRange) {
- isLiteral = false;
- isInRange = true;
- } else if (isInRange) {
- isInRange = false;
- } else if (s.charAt(l) === "]") {
- isInRange = true;
- } else {
- if (option.regexdash !== (l === 2 || (l === 3 &&
- s.charAt(1) === "^"))) {
- warningAt("Unescaped '{a}'.",
- line, from + l - 1, "-");
- }
- isLiteral = true;
- }
- break;
- case "]":
- if (isInRange && !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;
-
- // \w, \s and \d are never part of a character range
- if (/[wsd]/i.test(c)) {
- if (isInRange) {
- warningAt("Unescaped '{a}'.",
- line, from + l, "-");
- isInRange = false;
- }
- isLiteral = false;
- } else if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "/":
- warningAt("Unescaped '{a}'.",
- line, from + l - 1, "/");
-
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- case "<":
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = true;
- }
- break;
- default:
- if (isInRange) {
- isInRange = false;
- } else {
- isLiteral = 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);
- break; // No reason to continue checking numbers.
- }
- 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, token) {
- if (t === "hasOwnProperty") {
- warning("'hasOwnProperty' is a really bad name.");
- }
-
- // Define t in the current function in the current scope.
- if (type === "exception") {
- if (is_own(funct["(context)"], t)) {
- if (funct[t] !== true && !option.node) {
- warning("Value of '{a}' may be overwritten in IE.", nexttoken, t);
- }
- }
- }
-
- 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 && type !== "exception") {
- warning("'{a}' is already defined.", nexttoken, t);
- }
- }
- }
-
- funct[t] = type;
-
- if (token) {
- funct["(tokens)"][t] = token;
- }
-
- 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 nt = nexttoken;
- var o = nt.value;
- var quotmarkValue = option.quotmark;
- var predef = {};
- var b, obj, filter, t, tn, v, minus;
-
- switch (o) {
- case "*/":
- error("Unbegun comment.");
- break;
- case "/*members":
- case "/*member":
- o = "/*members";
- if (!membersOnly) {
- membersOnly = {};
- }
- obj = membersOnly;
- option.quotmark = false;
- break;
- case "/*jshint":
- case "/*jslint":
- obj = option;
- filter = boolOptions;
- break;
- case "/*global":
- obj = predef;
- break;
- default:
- error("What?");
- }
-
- t = lex.token();
-
-loop:
- for (;;) {
- minus = false;
- for (;;) {
- if (t.type === "special" && t.value === "*/") {
- break loop;
- }
- if (t.id !== "(endline)" && t.id !== ",") {
- break;
- }
- t = lex.token();
- }
-
- if (o === "/*global" && t.value === "-") {
- minus = true;
- 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 (o === "/*jshint") {
- checkOption(t.value, t);
- }
-
- var numericVals = [
- "maxstatements",
- "maxparams",
- "maxdepth",
- "maxcomplexity",
- "maxerr",
- "maxlen",
- "indent"
- ];
-
- if (numericVals.indexOf(t.value) > -1 && (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);
- }
-
- if (t.value === "indent")
- obj.white = true;
-
- obj[t.value] = b;
- } else if (t.value === "validthis") {
- if (funct["(global)"]) {
- error("Option 'validthis' can't be used in a global scope.");
- } else {
- if (v.value === "true" || v.value === "false")
- obj[t.value] = v.value === "true";
- else
- error("Bad option value.", v);
- }
- } else if (t.value === "quotmark" && (o === "/*jshint")) {
- switch (v.value) {
- case "true":
- obj.quotmark = true;
- break;
- case "false":
- obj.quotmark = false;
- break;
- case "double":
- case "single":
- obj.quotmark = v.value;
- break;
- default:
- error("Bad option value.", v);
- }
- } else if (v.value === "true" || v.value === "false") {
- if (o === "/*jslint") {
- tn = renamedOptions[t.value] || t.value;
- obj[tn] = v.value === "true";
- if (invertedOptions[tn] !== undefined) {
- obj[tn] = !obj[tn];
- }
- } else {
- obj[t.value] = v.value === "true";
- }
-
- if (t.value === "newcap")
- obj["(explicitNewcap)"] = true;
- } else {
- error("Bad option value.", v);
- }
- t = lex.token();
- } else {
- if (o === "/*jshint" || o === "/*jslint") {
- error("Missing option value.", t);
- }
-
- obj[t.value] = false;
-
- if (o === "/*global" && minus === true) {
- JSHINT.blacklist[t.value] = t.value;
- updatePredefined();
- }
-
- t = v;
- }
- }
-
- if (o === "/*members") {
- option.quotmark = quotmarkValue;
- }
-
- combine(predefined, predef);
-
- for (var key in predef) {
- if (is_own(predef, key)) {
- declared[key] = nt;
- }
- }
-
- 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, isObject = 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";
- isObject = token.value === "Object";
-
- // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
- // Line breaks in IfStatement heads exist to satisfy the checkJSHint
- // "Line too long." error.
- if (left && (left.value || (left.first && left.first.value))) {
- // If the left.value is not "new", or the left.first.value is a "."
- // then safely assume that this is not "new Array()" and possibly
- // not "new Object()"...
- if (left.value !== "new" ||
- (left.first && left.first.value && left.first.value === ".")) {
- isArray = false;
- // ...In the case of Object, if the left.value and token.value
- // are not equal, then safely assume that this not "new Object()"
- if (left.value !== token.value) {
- isObject = false;
- }
- }
- }
-
- advance();
- if (isArray && token.id === "(" && nexttoken.id === ")")
- warning("Use the array literal notation [].", token);
- if (isObject && token.id === "(" && nexttoken.id === ")")
- warning("Use the object 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) {
- left.from += (left.character - left.from);
- warning("Unexpected space after '{a}'.", left, 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.value === ";" && right.value === ";") {
- return;
- }
- if (left.line === right.line && left.character === right.from) {
- left.from += (left.character - left.from);
- warning("Missing space after '{a}'.",
- left, 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) {
- left.from += (left.character - left.from);
- warning("Missing space after '{a}'.",
- left, 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.laxcomma) {
- if (comma.first) {
- warning("Comma warnings can be turned off with 'laxcomma'");
- comma.first = false;
- }
- warning("Bad line breaking before '{a}'.", token, nexttoken.id);
- }
- } else if (!token.comment && token.character !== nexttoken.from && option.white) {
- token.from += (token.character - token.from);
- warning("Unexpected space after '{a}'.", token, 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 (s === "in" && left.id === "!") {
- warning("Confusing use of '{a}'.", left, "!");
- }
- 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 (isIdentifier(left, "NaN") || isIdentifier(right, "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}'.", right, "!");
- }
- 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) {
- symbol(s, 20).exps = true;
-
- return infix(s, function (left, that) {
- 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 (option.esnext && funct[left.value] === "const") {
- warning("Attempting to override '{a}' which is a constant", left, left.value);
- }
-
- 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) {
- 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") {
- if (!option.latedef) {
- break;
- }
- 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;
-
- if (t.id === ";") {
- 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 && nexttoken.value !== "{") {
- 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;
- }
-
- // Is it a lonely block?
-
- if (t.id === "{") {
- block(true, true);
- return;
- }
-
- // 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.", t);
- }
-
- if (nexttoken.id === ",") {
- return comma();
- }
-
- if (nexttoken.id !== ";") {
- if (!option.asi) {
- // If this is the last statement in a block that ends on
- // the same line *and* option lastsemic is on, ignore the warning.
- // Otherwise, complain about missing semicolon.
- if (!option.lastsemic || nexttoken.id !== "}" ||
- nexttoken.line !== token.line) {
- warningAt("Missing semicolon.", token.line, token.character);
- }
- }
- } else {
- adjacent(token, nexttoken);
- advance(";");
- nonadjacent(token, nexttoken);
- }
- }
-
-// Restore the indentation.
-
- indent = i;
- scope = s;
- return r;
- }
-
-
- function statements(startLine) {
- var a = [], p;
-
- while (!nexttoken.reach && nexttoken.id !== "(end)") {
- if (nexttoken.id === ";") {
- p = peek();
- if (!p || p.id !== "(") {
- warning("Unnecessary semicolon.");
- }
- advance(";");
- } else {
- a.push(statement(startLine === nexttoken.line));
- }
- }
- return a;
- }
-
-
- /*
- * read all directives
- * recognizes a simple form of asi, but always
- * warns, if it is used
- */
- function directives() {
- var i, p, pn;
-
- for (;;) {
- if (nexttoken.id === "(string)") {
- p = peek(0);
- if (p.id === "(endline)") {
- i = 1;
- do {
- pn = peek(i);
- i = i + 1;
- } while (pn.id === "(endline)");
-
- if (pn.id !== ";") {
- if (pn.id !== "(string)" && pn.id !== "(number)" &&
- pn.id !== "(regexp)" && pn.identifier !== true &&
- pn.id !== "}") {
- break;
- }
- warning("Missing semicolon.", nexttoken);
- } else {
- p = pn;
- }
- } else if (p.id === "}") {
- // directive with no other statements, warn about missing semicolon
- warning("Missing semicolon.", p);
- } else if (p.id !== ";") {
- break;
- }
-
- indentation();
- advance();
- if (directive[token.value]) {
- warning("Unnecessary directive \"{a}\".", token, token.value);
- }
-
- if (token.value === "use strict") {
- if (!option["(explicitNewcap)"])
- option.newcap = true;
- option.undef = true;
- }
-
- // there's no directive negation, so always set to true
- directive[token.value] = true;
-
- if (p.id === ";") {
- advance(";");
- }
- continue;
- }
- break;
- }
- }
-
-
- /*
- * 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).
- * isfunc - true if block is a function body
- */
- function block(ordinary, stmt, isfunc) {
- var a,
- b = inblock,
- old_indent = indent,
- m,
- s = scope,
- t,
- line,
- d;
-
- inblock = ordinary;
-
- if (!ordinary || !option.funcscope)
- scope = Object.create(scope);
-
- nonadjacent(token, nexttoken);
- t = nexttoken;
-
- var metrics = funct["(metrics)"];
- metrics.nestedBlockDepth += 1;
- metrics.verifyMaxNestedBlockDepthPerFunction();
-
- if (nexttoken.id === "{") {
- advance("{");
- line = token.line;
- if (nexttoken.id !== "}") {
- indent += option.indent;
- while (!ordinary && nexttoken.from > indent) {
- indent += option.indent;
- }
-
- if (isfunc) {
- m = {};
- for (d in directive) {
- if (is_own(directive, d)) {
- m[d] = directive[d];
- }
- }
- directives();
-
- if (option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !directive["use strict"]) {
- warning("Missing \"use strict\" statement.");
- }
- }
- }
-
- a = statements(line);
-
- metrics.statementCount += a.length;
-
- if (isfunc) {
- directive = m;
- }
-
- indent -= option.indent;
- if (line !== nexttoken.line) {
- indentation();
- }
- } else if (line !== nexttoken.line) {
- 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;
- indent += option.indent;
- // test indentation only if statement is in new line
- a = [statement(nexttoken.line === token.line)];
- indent -= option.indent;
- noreach = false;
- }
- funct["(verb)"] = null;
- if (!ordinary || !option.funcscope) scope = s;
- inblock = b;
- if (ordinary && option.noempty && (!a || a.length === 0)) {
- warning("Empty block.");
- }
- metrics.nestedBlockDepth -= 1;
- 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;
- }
- } else if (funct["(global)"]) {
- // 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.
-
- if (option.undef && typeof predefined[v] !== "boolean") {
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (nexttoken && (nexttoken.value === "." || nexttoken.value === "["))) {
-
- isundef(funct, "'{a}' is not defined.", token, v);
- }
- }
-
- note_implied(token);
- } else {
- // If the name is already defined in the current
- // function, but not as outer, then there is a scope error.
-
- 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 (option.undef) {
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (nexttoken &&
- (nexttoken.value === "." || nexttoken.value === "["))) {
-
- isundef(funct, "'{a}' is not defined.", token, v);
- }
- }
- 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":
- 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("</").reach = true;
- delim("<!");
- delim("<!--");
- 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 (directive["use strict"] && funct["(global)"]) {
- warning("Strict violation.", x);
- }
- });
- reservevar("eval");
- reservevar("false");
- reservevar("Infinity");
- reservevar("null");
- reservevar("this", function (x) {
- if (directive["use strict"] && !option.validthis && ((funct["(statement)"] &&
- funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
- warning("Possible 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) {
- 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("<");
- 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 "Number":
- case "String":
- case "Boolean":
- case "Math":
- case "JSON":
- warning("Do not use {a} as a constructor.", prevtoken, 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") && !is_own(global, c.value)) {
- 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.",
- token, token.value);
- }
- 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 (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
- if (option.noarg)
- warning("Avoid arguments.{a}.", left, m);
- else if (directive["use strict"])
- error("Strict violation.");
- } 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 ("Number String Boolean Date Object".indexOf(left.value) === -1) {
- 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.", token);
- }
- if (!option.evil) {
- if (left.value === "eval" || left.value === "Function" ||
- left.value === "execScript") {
- warning("eval is evil.", left);
-
- if (p[0] && [0].id === "(string)") {
- addInternalSrc(left, p[0].value);
- }
- } 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);
- addInternalSrc(left, p[0].value);
-
- // window.setTimeout/setInterval
- } else if (p[0] && p[0].id === "(string)" &&
- left.value === "." &&
- left.left.value === "window" &&
- (left.right === "setTimeout" ||
- left.right === "setInterval")) {
- warning(
- "Implied eval is evil. Pass a function instead of a string.", left);
- addInternalSrc(left, p[0].value);
- }
- }
- 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 !== "(" &&
- (nexttoken.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
- 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.",
- prevtoken, 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 === ",") {
- if (!option.es5)
- 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 next = nexttoken;
- var params = [];
- var ident;
-
- advance("(");
- nospace();
-
- if (nexttoken.id === ")") {
- advance(")");
- return;
- }
-
- for (;;) {
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", token);
- if (nexttoken.id === ",") {
- comma();
- } else {
- advance(")", next);
- nospace(prevtoken, token);
- return params;
- }
- }
- }
-
-
- function doFunction(name, statement) {
- var f;
- var oldOption = option;
- var oldScope = scope;
-
- option = Object.create(option);
- scope = Object.create(scope);
-
- funct = {
- "(name)" : name || "\"" + anonname + "\"",
- "(line)" : nexttoken.line,
- "(character)": nexttoken.character,
- "(context)" : funct,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(metrics)" : createMetrics(nexttoken),
- "(scope)" : scope,
- "(statement)": statement,
- "(tokens)" : {}
- };
-
- f = funct;
- token.funct = funct;
-
- functions.push(funct);
-
- if (name) {
- addlabel(name, "function");
- }
-
- funct["(params)"] = functionparams();
- funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
-
- block(false, false, true);
-
- funct["(metrics)"].verifyMaxStatementsPerFunction();
- funct["(metrics)"].verifyMaxComplexityPerFunction();
-
- scope = oldScope;
- option = oldOption;
- funct["(last)"] = token.line;
- funct["(lastcharacter)"] = token.character;
- funct = funct["(context)"];
-
- return f;
- }
-
- function createMetrics(functionStartToken) {
- return {
- statementCount: 0,
- nestedBlockDepth: -1,
- ComplexityCount: 1,
- verifyMaxStatementsPerFunction: function () {
- if (option.maxstatements &&
- this.statementCount > option.maxstatements) {
- var message = "Too many statements per function (" + this.statementCount + ").";
- warning(message, functionStartToken);
- }
- },
-
- verifyMaxParametersPerFunction: function (params) {
- params = params || [];
-
- if (option.maxparams && params.length > option.maxparams) {
- var message = "Too many parameters per function (" + params.length + ").";
- warning(message, functionStartToken);
- }
- },
-
- verifyMaxNestedBlockDepthPerFunction: function () {
- if (option.maxdepth &&
- this.nestedBlockDepth > 0 &&
- this.nestedBlockDepth === option.maxdepth + 1) {
- var message = "Blocks are nested too deeply (" + this.nestedBlockDepth + ").";
- warning(message);
- }
- },
-
- verifyMaxComplexityPerFunction: function () {
- var max = option.maxcomplexity;
- var cc = this.ComplexityCount;
- if (max && cc > max) {
- var message = "Cyclomatic complexity is too high per function (" + cc + ").";
- warning(message, functionStartToken);
- }
- }
- };
- }
-
- function increaseComplexityCount() {
- funct["(metrics)"].ComplexityCount += 1;
- }
-
-
- (function (x) {
- x.nud = function () {
- var b, f, i, p, t;
- var props = {}; // All properties, including accessors
-
- function saveProperty(name, token) {
- if (props[name] && is_own(props, name))
- warning("Duplicate member '{a}'.", nexttoken, i);
- else
- props[name] = {};
-
- props[name].basic = true;
- props[name].basicToken = token;
- }
-
- function saveSetter(name, token) {
- if (props[name] && is_own(props, name)) {
- if (props[name].basic || props[name].setter)
- warning("Duplicate member '{a}'.", nexttoken, i);
- } else {
- props[name] = {};
- }
-
- props[name].setter = true;
- props[name].setterToken = token;
- }
-
- function saveGetter(name) {
- if (props[name] && is_own(props, name)) {
- if (props[name].basic || props[name].getter)
- warning("Duplicate member '{a}'.", nexttoken, i);
- } else {
- props[name] = {};
- }
-
- props[name].getter = true;
- props[name].getterToken = token;
- }
-
- 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.");
- }
- saveGetter(i);
- t = nexttoken;
- adjacent(token, nexttoken);
- f = doFunction();
- p = f["(params)"];
- if (p) {
- warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
- }
- adjacent(token, nexttoken);
- } else if (nexttoken.value === "set" && peek().id !== ":") {
- advance("set");
- if (!option.es5) {
- error("get/set are ES5 features.");
- }
- i = property_name();
- if (!i) {
- error("Missing property name.");
- }
- saveSetter(i, nexttoken);
- t = nexttoken;
- adjacent(token, nexttoken);
- f = doFunction();
- p = f["(params)"];
- if (!p || p.length !== 1) {
- warning("Expected a single parameter in set {a} function.", t, i);
- }
- } else {
- i = property_name();
- saveProperty(i, nexttoken);
- if (typeof i !== "string") {
- break;
- }
- advance(":");
- nonadjacent(token, nexttoken);
- expression(10);
- }
-
- 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);
-
- // Check for lonely setters if in the ES5 mode.
- if (option.es5) {
- for (var name in props) {
- if (is_own(props, name) && props[name].setter && !props[name].getter) {
- warning("Setter is defined without getter.", props[name].setterToken);
- }
- }
- }
- return this;
- };
- x.fud = function () {
- error("Expected to see a statement and instead saw a block.", token);
- };
- }(delim("{")));
-
-// This Function is called when esnext option is set to true
-// it adds the `const` statement to JSHINT
-
- useESNextSyntax = function () {
- var conststatement = stmt("const", function (prefix) {
- var id, name, value;
-
- this.first = [];
- for (;;) {
- nonadjacent(token, nexttoken);
- id = identifier();
- if (funct[id] === "const") {
- warning("const '" + id + "' has already been declared");
- }
- if (funct["(global)"] && predefined[id] === false) {
- warning("Redefinition of '{a}'.", token, id);
- }
- addlabel(id, "const");
- if (prefix) {
- break;
- }
- name = token;
- this.first.push(token);
-
- if (nexttoken.id !== "=") {
- warning("const " +
- "'{a}' is initialized to 'undefined'.", token, id);
- }
-
- 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("Constant {a} was not declared correctly.",
- nexttoken, nexttoken.value);
- }
- value = expression(0);
- name.first = value;
- }
-
- if (nexttoken.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- conststatement.exps = true;
- };
-
- 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 (option.esnext && funct[id] === "const") {
- warning("const '" + id + "' has already been declared");
- }
-
- if (funct["(global)"] && predefined[id] === false) {
- warning("Redefinition of '{a}'.", token, id);
- }
-
- addlabel(id, "unused", token);
-
- 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();
- if (option.esnext && funct[i] === "const") {
- warning("const '" + i + "' has already been declared");
- }
- adjacent(token, nexttoken);
- addlabel(i, "unction", token);
-
- doFunction(i, { statement: 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;
- increaseComplexityCount();
- 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;
-
- function doCatch() {
- var oldScope = scope;
- var e;
-
- advance("catch");
- nonadjacent(token, nexttoken);
- advance("(");
-
- scope = Object.create(oldScope);
-
- e = nexttoken.value;
- if (nexttoken.type !== "(identifier)") {
- e = null;
- warning("Expected an identifier and instead saw '{a}'.", nexttoken, e);
- }
-
- advance();
- advance(")");
-
- funct = {
- "(name)" : "(catch)",
- "(line)" : nexttoken.line,
- "(character)": nexttoken.character,
- "(context)" : funct,
- "(breakage)" : funct["(breakage)"],
- "(loopage)" : funct["(loopage)"],
- "(scope)" : scope,
- "(statement)": false,
- "(metrics)" : createMetrics(nexttoken),
- "(catch)" : true,
- "(tokens)" : {}
- };
-
- if (e) {
- addlabel(e, "exception");
- }
-
- token.funct = funct;
- functions.push(funct);
-
- block(false);
-
- scope = oldScope;
-
- funct["(last)"] = token.line;
- funct["(lastcharacter)"] = token.character;
- funct = funct["(context)"];
- }
-
- block(false);
-
- if (nexttoken.id === "catch") {
- increaseComplexityCount();
- doCatch();
- b = true;
- }
-
- 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;
- increaseComplexityCount();
- 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;
-
- blockstmt("with", function () {
- var t = nexttoken;
- if (directive["use strict"]) {
- error("'with' is not allowed in strict mode.", token);
- } else if (!option.withstmt) {
- warning("Don't use 'with'.", token);
- }
-
- advance("(");
- nonadjacent(this, t);
- nospace();
- expression(0);
- advance(")", t);
- nospace(prevtoken, token);
- block(true, true);
-
- return this;
- });
-
- 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));
- increaseComplexityCount();
- 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") {
- if (!option.onecase)
- 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 ":":
- g = false;
- statements();
- break;
- default:
- error("Missing ':' on a case clause.", token);
- return;
- }
- } else {
- if (token.id === ":") {
- advance(":");
- error("Unexpected '{a}'.", token, ":");
- statements();
- } else {
- error("Expected '{a}' and instead saw '{b}'.",
- nexttoken, "case", nexttoken.value);
- return;
- }
- }
- }
- }
- }).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;
- increaseComplexityCount();
-
- 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;
- increaseComplexityCount();
- 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 && (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);
-
- if (!option.asi)
- 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);
-
- if (!option.asi)
- 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 () {
- if (this.line === nexttoken.line) {
- if (nexttoken.id === "(regexp)")
- warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
-
- if (nexttoken.id !== ";" && !nexttoken.reach) {
- nonadjacent(token, nexttoken);
- if (peek().value === "=" && !option.boss) {
- warningAt("Did you mean to return a conditional instead of an assignment?",
- token.line, token.character + 1);
- }
- this.first = expression(0);
- }
- } else if (!option.asi) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- 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__" &&
- !option.proto) || (nexttoken.value === "__iterator__" &&
- !option.iterator)) {
- warning("The '{a}' key may produce unexpected results.",
- 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, x;
- var optionKeys;
- var newOptionObj = {};
-
- if (o && o.scope) {
- JSHINT.scope = o.scope;
- } else {
- JSHINT.errors = [];
- JSHINT.undefs = [];
- JSHINT.internals = [];
- JSHINT.blacklist = {};
- JSHINT.scope = "(main)";
- }
-
- predefined = Object.create(standard);
- declared = Object.create(null);
- combine(predefined, g || {});
-
- if (o) {
- a = o.predef;
- if (a) {
- if (!Array.isArray(a) && typeof a === "object") {
- a = Object.keys(a);
- }
- a.forEach(function (item) {
- var slice;
- if (item[0] === "-") {
- slice = item.slice(1);
- JSHINT.blacklist[slice] = slice;
- } else {
- predefined[item] = true;
- }
- });
- }
-
- optionKeys = Object.keys(o);
- for (x = 0; x < optionKeys.length; x++) {
- newOptionObj[optionKeys[x]] = o[optionKeys[x]];
-
- if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
- newOptionObj["(explicitNewcap)"] = true;
-
- if (optionKeys[x] === "indent")
- newOptionObj.white = true;
- }
- }
-
- option = newOptionObj;
-
- 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,
- "(tokens)": {},
- "(metrics)": createMetrics(nexttoken)
- };
- functions = [funct];
- urls = [];
- stack = null;
- member = {};
- membersOnly = null;
- implied = {};
- inblock = false;
- lookahead = [];
- jsonmode = false;
- warnings = 0;
- lines = [];
- unuseds = [];
-
- if (!isString(s) && !Array.isArray(s)) {
- errorAt("Input is neither a string nor an array of strings.", 0);
- return false;
- }
-
- if (isString(s) && /^\s*$/g.test(s)) {
- errorAt("Input is an empty string.", 0);
- return false;
- }
-
- if (s.length === 0) {
- errorAt("Input is an empty array.", 0);
- return false;
- }
-
- lex.init(s);
-
- prereg = true;
- directive = {};
-
- prevtoken = token = nexttoken = syntax["(begin)"];
-
- // Check options
- for (var name in o) {
- if (is_own(o, name)) {
- checkOption(name, token);
- }
- }
-
- assume();
-
- // combine the passed globals after we've assumed all our options
- combine(predefined, g || {});
-
- //reset values
- comma.first = true;
- quotmark = undefined;
-
- try {
- advance();
- switch (nexttoken.id) {
- case "{":
- case "[":
- option.laxbreak = true;
- jsonmode = true;
- jsonValue();
- break;
- default:
- directives();
- if (directive["use strict"] && !option.globalstrict) {
- warning("Use the function form of \"use strict\".", prevtoken);
- }
-
- statements();
- }
- advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined);
-
- var markDefined = function (name, context) {
- do {
- if (typeof context[name] === "string") {
- // JSHINT marks unused variables as 'unused' and
- // unused function declaration as 'unction'. This
- // code changes such instances back 'var' and
- // 'closure' so that the code in JSHINT.data()
- // doesn't think they're unused.
-
- if (context[name] === "unused")
- context[name] = "var";
- else if (context[name] === "unction")
- context[name] = "closure";
-
- return true;
- }
-
- context = context["(context)"];
- } while (context);
-
- return false;
- };
-
- var clearImplied = function (name, line) {
- if (!implied[name])
- return;
-
- var newImplied = [];
- for (var i = 0; i < implied[name].length; i += 1) {
- if (implied[name][i] !== line)
- newImplied.push(implied[name][i]);
- }
-
- if (newImplied.length === 0)
- delete implied[name];
- else
- implied[name] = newImplied;
- };
-
- var warnUnused = function (name, token) {
- var line = token.line;
- var chr = token.character;
-
- if (option.unused)
- warningAt("'{a}' is defined but never used.", line, chr, name);
-
- unuseds.push({
- name: name,
- line: line,
- character: chr
- });
- };
-
- var checkUnused = function (func, key) {
- var type = func[key];
- var token = func["(tokens)"][key];
-
- if (key.charAt(0) === "(")
- return;
-
- if (type !== "unused" && type !== "unction")
- return;
-
- // Params are checked separately from other variables.
- if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
- return;
-
- warnUnused(key, token);
- };
-
- // Check queued 'x is not defined' instances to see if they're still undefined.
- for (i = 0; i < JSHINT.undefs.length; i += 1) {
- k = JSHINT.undefs[i].slice(0);
-
- if (markDefined(k[2].value, k[0])) {
- clearImplied(k[2].value, k[2].line);
- } else {
- warning.apply(warning, k.slice(1));
- }
- }
-
- functions.forEach(function (func) {
- for (var key in func) {
- if (is_own(func, key)) {
- checkUnused(func, key);
- }
- }
-
- if (!func["(params)"])
- return;
-
- var params = func["(params)"].slice();
- var param = params.pop();
- var type;
-
- while (param) {
- type = func[param];
-
- // 'undefined' is a special case for (function (window, undefined) { ... })();
- // patterns.
-
- if (param === "undefined")
- return;
-
- if (type !== "unused" && type !== "unction")
- return;
-
- warnUnused(param, func["(tokens)"][param]);
- param = params.pop();
- }
- });
-
- for (var key in declared) {
- if (is_own(declared, key) && !is_own(global, key)) {
- warnUnused(key, declared[key]);
- }
- }
- } catch (e) {
- if (e) {
- var nt = nexttoken || {};
- JSHINT.errors.push({
- raw : e.raw,
- reason : e.message,
- line : e.line || nt.line,
- character : e.character || nt.from
- }, null);
- }
- }
-
- // Loop over the listed "internals", and check them as well.
-
- if (JSHINT.scope === "(main)") {
- o = o || {};
-
- for (i = 0; i < JSHINT.internals.length; i += 1) {
- k = JSHINT.internals[i];
- o.scope = k.elem;
- itself(k.value, o, g);
- }
- }
-
- return JSHINT.errors.length === 0;
- };
-
- // Data summary.
- itself.data = function () {
- var data = {
- functions: [],
- options: option
- };
- var implieds = [];
- var members = [];
- var fu, f, i, j, n, globals;
-
- 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 (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.character = f["(character)"];
- fu.last = f["(last)"];
- fu.lastcharacter = f["(lastcharacter)"];
- data.functions.push(fu);
- }
-
- if (unuseds.length > 0) {
- data.unused = unuseds;
- }
-
- members = [];
- for (n in member) {
- if (typeof member[n] === "number") {
- data.member = member;
- break;
- }
- }
-
- return data;
- };
-
- itself.jshint = itself;
-
- return itself;
-}());
-
-// Make JSHINT a Node module, if possible.
-if (typeof exports === "object" && exports) {
- exports.JSHINT = JSHINT;
-} \ No newline at end of file
diff --git a/apps/it/static/js/ui/external/qunit.css b/apps/it/static/js/ui/external/qunit.css
deleted file mode 100644
index d7fc0c8..0000000
--- a/apps/it/static/js/ui/external/qunit.css
+++ /dev/null
@@ -1,244 +0,0 @@
-/**
- * QUnit v1.11.0 - A JavaScript Unit Testing Framework
- *
- * http://qunitjs.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-
-/** Font Family and Sizes */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
- font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
-}
-
-#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
-#qunit-tests { font-size: smaller; }
-
-
-/** Resets */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
- margin: 0;
- padding: 0;
-}
-
-
-/** Header */
-
-#qunit-header {
- padding: 0.5em 0 0.5em 1em;
-
- color: #8699a4;
- background-color: #0d3349;
-
- font-size: 1.5em;
- line-height: 1em;
- font-weight: normal;
-
- border-radius: 5px 5px 0 0;
- -moz-border-radius: 5px 5px 0 0;
- -webkit-border-top-right-radius: 5px;
- -webkit-border-top-left-radius: 5px;
-}
-
-#qunit-header a {
- text-decoration: none;
- color: #c2ccd1;
-}
-
-#qunit-header a:hover,
-#qunit-header a:focus {
- color: #fff;
-}
-
-#qunit-testrunner-toolbar label {
- display: inline-block;
- padding: 0 .5em 0 .1em;
-}
-
-#qunit-banner {
- height: 5px;
-}
-
-#qunit-testrunner-toolbar {
- padding: 0.5em 0 0.5em 2em;
- color: #5E740B;
- background-color: #eee;
- overflow: hidden;
-}
-
-#qunit-userAgent {
- padding: 0.5em 0 0.5em 2.5em;
- background-color: #2b81af;
- color: #fff;
- text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
-}
-
-#qunit-modulefilter-container {
- float: right;
-}
-
-/** Tests: Pass/Fail */
-
-#qunit-tests {
- list-style-position: inside;
-}
-
-#qunit-tests li {
- padding: 0.4em 0.5em 0.4em 2.5em;
- border-bottom: 1px solid #fff;
- list-style-position: inside;
-}
-
-#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
- display: none;
-}
-
-#qunit-tests li strong {
- cursor: pointer;
-}
-
-#qunit-tests li a {
- padding: 0.5em;
- color: #c2ccd1;
- text-decoration: none;
-}
-#qunit-tests li a:hover,
-#qunit-tests li a:focus {
- color: #000;
-}
-
-#qunit-tests li .runtime {
- float: right;
- font-size: smaller;
-}
-
-.qunit-assert-list {
- margin-top: 0.5em;
- padding: 0.5em;
-
- background-color: #fff;
-
- border-radius: 5px;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
-}
-
-.qunit-collapsed {
- display: none;
-}
-
-#qunit-tests table {
- border-collapse: collapse;
- margin-top: .2em;
-}
-
-#qunit-tests th {
- text-align: right;
- vertical-align: top;
- padding: 0 .5em 0 0;
-}
-
-#qunit-tests td {
- vertical-align: top;
-}
-
-#qunit-tests pre {
- margin: 0;
- white-space: pre-wrap;
- word-wrap: break-word;
-}
-
-#qunit-tests del {
- background-color: #e0f2be;
- color: #374e0c;
- text-decoration: none;
-}
-
-#qunit-tests ins {
- background-color: #ffcaca;
- color: #500;
- text-decoration: none;
-}
-
-/*** Test Counts */
-
-#qunit-tests b.counts { color: black; }
-#qunit-tests b.passed { color: #5E740B; }
-#qunit-tests b.failed { color: #710909; }
-
-#qunit-tests li li {
- padding: 5px;
- background-color: #fff;
- border-bottom: none;
- list-style-position: inside;
-}
-
-/*** Passing Styles */
-
-#qunit-tests li li.pass {
- color: #3c510c;
- background-color: #fff;
- border-left: 10px solid #C6E746;
-}
-
-#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
-#qunit-tests .pass .test-name { color: #366097; }
-
-#qunit-tests .pass .test-actual,
-#qunit-tests .pass .test-expected { color: #999999; }
-
-#qunit-banner.qunit-pass { background-color: #C6E746; }
-
-/*** Failing Styles */
-
-#qunit-tests li li.fail {
- color: #710909;
- background-color: #fff;
- border-left: 10px solid #EE5757;
- white-space: pre;
-}
-
-#qunit-tests > li:last-child {
- border-radius: 0 0 5px 5px;
- -moz-border-radius: 0 0 5px 5px;
- -webkit-border-bottom-right-radius: 5px;
- -webkit-border-bottom-left-radius: 5px;
-}
-
-#qunit-tests .fail { color: #000000; background-color: #EE5757; }
-#qunit-tests .fail .test-name,
-#qunit-tests .fail .module-name { color: #000000; }
-
-#qunit-tests .fail .test-actual { color: #EE5757; }
-#qunit-tests .fail .test-expected { color: green; }
-
-#qunit-banner.qunit-fail { background-color: #EE5757; }
-
-
-/** Result */
-
-#qunit-testresult {
- padding: 0.5em 0.5em 0.5em 2.5em;
-
- color: #2b81af;
- background-color: #D2E0E6;
-
- border-bottom: 1px solid white;
-}
-#qunit-testresult .module-name {
- font-weight: bold;
-}
-
-/** Fixture */
-
-#qunit-fixture {
- position: absolute;
- top: -10000px;
- left: -10000px;
- width: 1000px;
- height: 1000px;
-}
diff --git a/apps/it/static/js/ui/external/qunit.js b/apps/it/static/js/ui/external/qunit.js
deleted file mode 100644
index 302545f..0000000
--- a/apps/it/static/js/ui/external/qunit.js
+++ /dev/null
@@ -1,2152 +0,0 @@
-/**
- * QUnit v1.11.0 - A JavaScript Unit Testing Framework
- *
- * http://qunitjs.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-
-(function( window ) {
-
-var QUnit,
- assert,
- config,
- onErrorFnPrev,
- testId = 0,
- fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
- toString = Object.prototype.toString,
- hasOwn = Object.prototype.hasOwnProperty,
- // Keep a local reference to Date (GH-283)
- Date = window.Date,
- defined = {
- setTimeout: typeof window.setTimeout !== "undefined",
- sessionStorage: (function() {
- var x = "qunit-test-string";
- try {
- sessionStorage.setItem( x, x );
- sessionStorage.removeItem( x );
- return true;
- } catch( e ) {
- return false;
- }
- }())
- },
- /**
- * Provides a normalized error string, correcting an issue
- * with IE 7 (and prior) where Error.prototype.toString is
- * not properly implemented
- *
- * Based on http://es5.github.com/#x15.11.4.4
- *
- * @param {String|Error} error
- * @return {String} error message
- */
- errorString = function( error ) {
- var name, message,
- errorString = error.toString();
- if ( errorString.substring( 0, 7 ) === "[object" ) {
- name = error.name ? error.name.toString() : "Error";
- message = error.message ? error.message.toString() : "";
- if ( name && message ) {
- return name + ": " + message;
- } else if ( name ) {
- return name;
- } else if ( message ) {
- return message;
- } else {
- return "Error";
- }
- } else {
- return errorString;
- }
- },
- /**
- * Makes a clone of an object using only Array or Object as base,
- * and copies over the own enumerable properties.
- *
- * @param {Object} obj
- * @return {Object} New object with only the own properties (recursively).
- */
- objectValues = function( obj ) {
- // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
- /*jshint newcap: false */
- var key, val,
- vals = QUnit.is( "array", obj ) ? [] : {};
- for ( key in obj ) {
- if ( hasOwn.call( obj, key ) ) {
- val = obj[key];
- vals[key] = val === Object(val) ? objectValues(val) : val;
- }
- }
- return vals;
- };
-
-function Test( settings ) {
- extend( this, settings );
- this.assertions = [];
- this.testNumber = ++Test.count;
-}
-
-Test.count = 0;
-
-Test.prototype = {
- init: function() {
- var a, b, li,
- tests = id( "qunit-tests" );
-
- if ( tests ) {
- b = document.createElement( "strong" );
- b.innerHTML = this.nameHtml;
-
- // `a` initialized at top of scope
- a = document.createElement( "a" );
- a.innerHTML = "Rerun";
- a.href = QUnit.url({ testNumber: this.testNumber });
-
- li = document.createElement( "li" );
- li.appendChild( b );
- li.appendChild( a );
- li.className = "running";
- li.id = this.id = "qunit-test-output" + testId++;
-
- tests.appendChild( li );
- }
- },
- setup: function() {
- if ( this.module !== config.previousModule ) {
- if ( config.previousModule ) {
- runLoggingCallbacks( "moduleDone", QUnit, {
- name: config.previousModule,
- failed: config.moduleStats.bad,
- passed: config.moduleStats.all - config.moduleStats.bad,
- total: config.moduleStats.all
- });
- }
- config.previousModule = this.module;
- config.moduleStats = { all: 0, bad: 0 };
- runLoggingCallbacks( "moduleStart", QUnit, {
- name: this.module
- });
- } else if ( config.autorun ) {
- runLoggingCallbacks( "moduleStart", QUnit, {
- name: this.module
- });
- }
-
- config.current = this;
-
- this.testEnvironment = extend({
- setup: function() {},
- teardown: function() {}
- }, this.moduleTestEnvironment );
-
- this.started = +new Date();
- runLoggingCallbacks( "testStart", QUnit, {
- name: this.testName,
- module: this.module
- });
-
- // allow utility functions to access the current test environment
- // TODO why??
- QUnit.current_testEnvironment = this.testEnvironment;
-
- if ( !config.pollution ) {
- saveGlobal();
- }
- if ( config.notrycatch ) {
- this.testEnvironment.setup.call( this.testEnvironment );
- return;
- }
- try {
- this.testEnvironment.setup.call( this.testEnvironment );
- } catch( e ) {
- QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
- }
- },
- run: function() {
- config.current = this;
-
- var running = id( "qunit-testresult" );
-
- if ( running ) {
- running.innerHTML = "Running: <br/>" + this.nameHtml;
- }
-
- if ( this.async ) {
- QUnit.stop();
- }
-
- this.callbackStarted = +new Date();
-
- if ( config.notrycatch ) {
- this.callback.call( this.testEnvironment, QUnit.assert );
- this.callbackRuntime = +new Date() - this.callbackStarted;
- return;
- }
-
- try {
- this.callback.call( this.testEnvironment, QUnit.assert );
- this.callbackRuntime = +new Date() - this.callbackStarted;
- } catch( e ) {
- this.callbackRuntime = +new Date() - this.callbackStarted;
-
- QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
- // else next test will carry the responsibility
- saveGlobal();
-
- // Restart the tests if they're blocking
- if ( config.blocking ) {
- QUnit.start();
- }
- }
- },
- teardown: function() {
- config.current = this;
- if ( config.notrycatch ) {
- if ( typeof this.callbackRuntime === "undefined" ) {
- this.callbackRuntime = +new Date() - this.callbackStarted;
- }
- this.testEnvironment.teardown.call( this.testEnvironment );
- return;
- } else {
- try {
- this.testEnvironment.teardown.call( this.testEnvironment );
- } catch( e ) {
- QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
- }
- }
- checkPollution();
- },
- finish: function() {
- config.current = this;
- if ( config.requireExpects && this.expected === null ) {
- QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
- } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
- QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
- } else if ( this.expected === null && !this.assertions.length ) {
- QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
- }
-
- var i, assertion, a, b, time, li, ol,
- test = this,
- good = 0,
- bad = 0,
- tests = id( "qunit-tests" );
-
- this.runtime = +new Date() - this.started;
- config.stats.all += this.assertions.length;
- config.moduleStats.all += this.assertions.length;
-
- if ( tests ) {
- ol = document.createElement( "ol" );
- ol.className = "qunit-assert-list";
-
- for ( i = 0; i < this.assertions.length; i++ ) {
- assertion = this.assertions[i];
-
- li = document.createElement( "li" );
- li.className = assertion.result ? "pass" : "fail";
- li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
- ol.appendChild( li );
-
- if ( assertion.result ) {
- good++;
- } else {
- bad++;
- config.stats.bad++;
- config.moduleStats.bad++;
- }
- }
-
- // store result when possible
- if ( QUnit.config.reorder && defined.sessionStorage ) {
- if ( bad ) {
- sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
- } else {
- sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
- }
- }
-
- if ( bad === 0 ) {
- addClass( ol, "qunit-collapsed" );
- }
-
- // `b` initialized at top of scope
- b = document.createElement( "strong" );
- b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
-
- addEvent(b, "click", function() {
- var next = b.parentNode.lastChild,
- collapsed = hasClass( next, "qunit-collapsed" );
- ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
- });
-
- addEvent(b, "dblclick", function( e ) {
- var target = e && e.target ? e.target : window.event.srcElement;
- if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
- target = target.parentNode;
- }
- if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
- window.location = QUnit.url({ testNumber: test.testNumber });
- }
- });
-
- // `time` initialized at top of scope
- time = document.createElement( "span" );
- time.className = "runtime";
- time.innerHTML = this.runtime + " ms";
-
- // `li` initialized at top of scope
- li = id( this.id );
- li.className = bad ? "fail" : "pass";
- li.removeChild( li.firstChild );
- a = li.firstChild;
- li.appendChild( b );
- li.appendChild( a );
- li.appendChild( time );
- li.appendChild( ol );
-
- } else {
- for ( i = 0; i < this.assertions.length; i++ ) {
- if ( !this.assertions[i].result ) {
- bad++;
- config.stats.bad++;
- config.moduleStats.bad++;
- }
- }
- }
-
- runLoggingCallbacks( "testDone", QUnit, {
- name: this.testName,
- module: this.module,
- failed: bad,
- passed: this.assertions.length - bad,
- total: this.assertions.length,
- duration: this.runtime
- });
-
- QUnit.reset();
-
- config.current = undefined;
- },
-
- queue: function() {
- var bad,
- test = this;
-
- synchronize(function() {
- test.init();
- });
- function run() {
- // each of these can by async
- synchronize(function() {
- test.setup();
- });
- synchronize(function() {
- test.run();
- });
- synchronize(function() {
- test.teardown();
- });
- synchronize(function() {
- test.finish();
- });
- }
-
- // `bad` initialized at top of scope
- // defer when previous test run passed, if storage is available
- bad = QUnit.config.reorder && defined.sessionStorage &&
- +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
-
- if ( bad ) {
- run();
- } else {
- synchronize( run, true );
- }
- }
-};
-
-// Root QUnit object.
-// `QUnit` initialized at top of scope
-QUnit = {
-
- // call on start of module test to prepend name to all tests
- module: function( name, testEnvironment ) {
- config.currentModule = name;
- config.currentModuleTestEnvironment = testEnvironment;
- config.modules[name] = true;
- },
-
- asyncTest: function( testName, expected, callback ) {
- if ( arguments.length === 2 ) {
- callback = expected;
- expected = null;
- }
-
- QUnit.test( testName, expected, callback, true );
- },
-
- test: function( testName, expected, callback, async ) {
- var test,
- nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
-
- if ( arguments.length === 2 ) {
- callback = expected;
- expected = null;
- }
-
- if ( config.currentModule ) {
- nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
- }
-
- test = new Test({
- nameHtml: nameHtml,
- testName: testName,
- expected: expected,
- async: async,
- callback: callback,
- module: config.currentModule,
- moduleTestEnvironment: config.currentModuleTestEnvironment,
- stack: sourceFromStacktrace( 2 )
- });
-
- if ( !validTest( test ) ) {
- return;
- }
-
- test.queue();
- },
-
- // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
- expect: function( asserts ) {
- if (arguments.length === 1) {
- config.current.expected = asserts;
- } else {
- return config.current.expected;
- }
- },
-
- start: function( count ) {
- // QUnit hasn't been initialized yet.
- // Note: RequireJS (et al) may delay onLoad
- if ( config.semaphore === undefined ) {
- QUnit.begin(function() {
- // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
- setTimeout(function() {
- QUnit.start( count );
- });
- });
- return;
- }
-
- config.semaphore -= count || 1;
- // don't start until equal number of stop-calls
- if ( config.semaphore > 0 ) {
- return;
- }
- // ignore if start is called more often then stop
- if ( config.semaphore < 0 ) {
- config.semaphore = 0;
- QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
- return;
- }
- // A slight delay, to avoid any current callbacks
- if ( defined.setTimeout ) {
- window.setTimeout(function() {
- if ( config.semaphore > 0 ) {
- return;
- }
- if ( config.timeout ) {
- clearTimeout( config.timeout );
- }
-
- config.blocking = false;
- process( true );
- }, 13);
- } else {
- config.blocking = false;
- process( true );
- }
- },
-
- stop: function( count ) {
- config.semaphore += count || 1;
- config.blocking = true;
-
- if ( config.testTimeout && defined.setTimeout ) {
- clearTimeout( config.timeout );
- config.timeout = window.setTimeout(function() {
- QUnit.ok( false, "Test timed out" );
- config.semaphore = 1;
- QUnit.start();
- }, config.testTimeout );
- }
- }
-};
-
-// `assert` initialized at top of scope
-// Asssert helpers
-// All of these must either call QUnit.push() or manually do:
-// - runLoggingCallbacks( "log", .. );
-// - config.current.assertions.push({ .. });
-// We attach it to the QUnit object *after* we expose the public API,
-// otherwise `assert` will become a global variable in browsers (#341).
-assert = {
- /**
- * Asserts rough true-ish result.
- * @name ok
- * @function
- * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
- */
- ok: function( result, msg ) {
- if ( !config.current ) {
- throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
- }
- result = !!result;
-
- var source,
- details = {
- module: config.current.module,
- name: config.current.testName,
- result: result,
- message: msg
- };
-
- msg = escapeText( msg || (result ? "okay" : "failed" ) );
- msg = "<span class='test-message'>" + msg + "</span>";
-
- if ( !result ) {
- source = sourceFromStacktrace( 2 );
- if ( source ) {
- details.source = source;
- msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
- }
- }
- runLoggingCallbacks( "log", QUnit, details );
- config.current.assertions.push({
- result: result,
- message: msg
- });
- },
-
- /**
- * Assert that the first two arguments are equal, with an optional message.
- * Prints out both actual and expected values.
- * @name equal
- * @function
- * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
- */
- equal: function( actual, expected, message ) {
- /*jshint eqeqeq:false */
- QUnit.push( expected == actual, actual, expected, message );
- },
-
- /**
- * @name notEqual
- * @function
- */
- notEqual: function( actual, expected, message ) {
- /*jshint eqeqeq:false */
- QUnit.push( expected != actual, actual, expected, message );
- },
-
- /**
- * @name propEqual
- * @function
- */
- propEqual: function( actual, expected, message ) {
- actual = objectValues(actual);
- expected = objectValues(expected);
- QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
- },
-
- /**
- * @name notPropEqual
- * @function
- */
- notPropEqual: function( actual, expected, message ) {
- actual = objectValues(actual);
- expected = objectValues(expected);
- QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
- },
-
- /**
- * @name deepEqual
- * @function
- */
- deepEqual: function( actual, expected, message ) {
- QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
- },
-
- /**
- * @name notDeepEqual
- * @function
- */
- notDeepEqual: function( actual, expected, message ) {
- QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
- },
-
- /**
- * @name strictEqual
- * @function
- */
- strictEqual: function( actual, expected, message ) {
- QUnit.push( expected === actual, actual, expected, message );
- },
-
- /**
- * @name notStrictEqual
- * @function
- */
- notStrictEqual: function( actual, expected, message ) {
- QUnit.push( expected !== actual, actual, expected, message );
- },
-
- "throws": function( block, expected, message ) {
- var actual,
- expectedOutput = expected,
- ok = false;
-
- // 'expected' is optional
- if ( typeof expected === "string" ) {
- message = expected;
- expected = null;
- }
-
- config.current.ignoreGlobalErrors = true;
- try {
- block.call( config.current.testEnvironment );
- } catch (e) {
- actual = e;
- }
- config.current.ignoreGlobalErrors = false;
-
- if ( actual ) {
- // we don't want to validate thrown error
- if ( !expected ) {
- ok = true;
- expectedOutput = null;
- // expected is a regexp
- } else if ( QUnit.objectType( expected ) === "regexp" ) {
- ok = expected.test( errorString( actual ) );
- // expected is a constructor
- } else if ( actual instanceof expected ) {
- ok = true;
- // expected is a validation function which returns true is validation passed
- } else if ( expected.call( {}, actual ) === true ) {
- expectedOutput = null;
- ok = true;
- }
-
- QUnit.push( ok, actual, expectedOutput, message );
- } else {
- QUnit.pushFailure( message, null, 'No exception was thrown.' );
- }
- }
-};
-
-/**
- * @deprecate since 1.8.0
- * Kept assertion helpers in root for backwards compatibility.
- */
-extend( QUnit, assert );
-
-/**
- * @deprecated since 1.9.0
- * Kept root "raises()" for backwards compatibility.
- * (Note that we don't introduce assert.raises).
- */
-QUnit.raises = assert[ "throws" ];
-
-/**
- * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
- * Kept to avoid TypeErrors for undefined methods.
- */
-QUnit.equals = function() {
- QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
-};
-QUnit.same = function() {
- QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
-};
-
-// We want access to the constructor's prototype
-(function() {
- function F() {}
- F.prototype = QUnit;
- QUnit = new F();
- // Make F QUnit's constructor so that we can add to the prototype later
- QUnit.constructor = F;
-}());
-
-/**
- * Config object: Maintain internal state
- * Later exposed as QUnit.config
- * `config` initialized at top of scope
- */
-config = {
- // The queue of tests to run
- queue: [],
-
- // block until document ready
- blocking: true,
-
- // when enabled, show only failing tests
- // gets persisted through sessionStorage and can be changed in UI via checkbox
- hidepassed: false,
-
- // by default, run previously failed tests first
- // very useful in combination with "Hide passed tests" checked
- reorder: true,
-
- // by default, modify document.title when suite is done
- altertitle: true,
-
- // when enabled, all tests must call expect()
- requireExpects: false,
-
- // add checkboxes that are persisted in the query-string
- // when enabled, the id is set to `true` as a `QUnit.config` property
- urlConfig: [
- {
- id: "noglobals",
- label: "Check for Globals",
- tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
- },
- {
- id: "notrycatch",
- label: "No try-catch",
- tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
- }
- ],
-
- // Set of all modules.
- modules: {},
-
- // logging callback queues
- begin: [],
- done: [],
- log: [],
- testStart: [],
- testDone: [],
- moduleStart: [],
- moduleDone: []
-};
-
-// Export global variables, unless an 'exports' object exists,
-// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
-if ( typeof exports === "undefined" ) {
- extend( window, QUnit );
-
- // Expose QUnit object
- window.QUnit = QUnit;
-}
-
-// Initialize more QUnit.config and QUnit.urlParams
-(function() {
- var i,
- location = window.location || { search: "", protocol: "file:" },
- params = location.search.slice( 1 ).split( "&" ),
- length = params.length,
- urlParams = {},
- current;
-
- if ( params[ 0 ] ) {
- for ( i = 0; i < length; i++ ) {
- current = params[ i ].split( "=" );
- current[ 0 ] = decodeURIComponent( current[ 0 ] );
- // allow just a key to turn on a flag, e.g., test.html?noglobals
- current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
- urlParams[ current[ 0 ] ] = current[ 1 ];
- }
- }
-
- QUnit.urlParams = urlParams;
-
- // String search anywhere in moduleName+testName
- config.filter = urlParams.filter;
-
- // Exact match of the module name
- config.module = urlParams.module;
-
- config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
-
- // Figure out if we're running the tests from a server or not
- QUnit.isLocal = location.protocol === "file:";
-}());
-
-// Extend QUnit object,
-// these after set here because they should not be exposed as global functions
-extend( QUnit, {
- assert: assert,
-
- config: config,
-
- // Initialize the configuration options
- init: function() {
- extend( config, {
- stats: { all: 0, bad: 0 },
- moduleStats: { all: 0, bad: 0 },
- started: +new Date(),
- updateRate: 1000,
- blocking: false,
- autostart: true,
- autorun: false,
- filter: "",
- queue: [],
- semaphore: 1
- });
-
- var tests, banner, result,
- qunit = id( "qunit" );
-
- if ( qunit ) {
- qunit.innerHTML =
- "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
- "<h2 id='qunit-banner'></h2>" +
- "<div id='qunit-testrunner-toolbar'></div>" +
- "<h2 id='qunit-userAgent'></h2>" +
- "<ol id='qunit-tests'></ol>";
- }
-
- tests = id( "qunit-tests" );
- banner = id( "qunit-banner" );
- result = id( "qunit-testresult" );
-
- if ( tests ) {
- tests.innerHTML = "";
- }
-
- if ( banner ) {
- banner.className = "";
- }
-
- if ( result ) {
- result.parentNode.removeChild( result );
- }
-
- if ( tests ) {
- result = document.createElement( "p" );
- result.id = "qunit-testresult";
- result.className = "result";
- tests.parentNode.insertBefore( result, tests );
- result.innerHTML = "Running...<br/>&nbsp;";
- }
- },
-
- // Resets the test setup. Useful for tests that modify the DOM.
- reset: function() {
- var fixture = id( "qunit-fixture" );
- if ( fixture ) {
- fixture.innerHTML = config.fixture;
- }
- },
-
- // Trigger an event on an element.
- // @example triggerEvent( document.body, "click" );
- triggerEvent: function( elem, type, event ) {
- if ( document.createEvent ) {
- event = document.createEvent( "MouseEvents" );
- event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
- 0, 0, 0, 0, 0, false, false, false, false, 0, null);
-
- elem.dispatchEvent( event );
- } else if ( elem.fireEvent ) {
- elem.fireEvent( "on" + type );
- }
- },
-
- // Safe object type checking
- is: function( type, obj ) {
- return QUnit.objectType( obj ) === type;
- },
-
- objectType: function( obj ) {
- if ( typeof obj === "undefined" ) {
- return "undefined";
- // consider: typeof null === object
- }
- if ( obj === null ) {
- return "null";
- }
-
- var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
- type = match && match[1] || "";
-
- switch ( type ) {
- case "Number":
- if ( isNaN(obj) ) {
- return "nan";
- }
- return "number";
- case "String":
- case "Boolean":
- case "Array":
- case "Date":
- case "RegExp":
- case "Function":
- return type.toLowerCase();
- }
- if ( typeof obj === "object" ) {
- return "object";
- }
- return undefined;
- },
-
- push: function( result, actual, expected, message ) {
- if ( !config.current ) {
- throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
- }
-
- var output, source,
- details = {
- module: config.current.module,
- name: config.current.testName,
- result: result,
- message: message,
- actual: actual,
- expected: expected
- };
-
- message = escapeText( message ) || ( result ? "okay" : "failed" );
- message = "<span class='test-message'>" + message + "</span>";
- output = message;
-
- if ( !result ) {
- expected = escapeText( QUnit.jsDump.parse(expected) );
- actual = escapeText( QUnit.jsDump.parse(actual) );
- output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
-
- if ( actual !== expected ) {
- output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
- output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
- }
-
- source = sourceFromStacktrace();
-
- if ( source ) {
- details.source = source;
- output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
- }
-
- output += "</table>";
- }
-
- runLoggingCallbacks( "log", QUnit, details );
-
- config.current.assertions.push({
- result: !!result,
- message: output
- });
- },
-
- pushFailure: function( message, source, actual ) {
- if ( !config.current ) {
- throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
- }
-
- var output,
- details = {
- module: config.current.module,
- name: config.current.testName,
- result: false,
- message: message
- };
-
- message = escapeText( message ) || "error";
- message = "<span class='test-message'>" + message + "</span>";
- output = message;
-
- output += "<table>";
-
- if ( actual ) {
- output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
- }
-
- if ( source ) {
- details.source = source;
- output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
- }
-
- output += "</table>";
-
- runLoggingCallbacks( "log", QUnit, details );
-
- config.current.assertions.push({
- result: false,
- message: output
- });
- },
-
- url: function( params ) {
- params = extend( extend( {}, QUnit.urlParams ), params );
- var key,
- querystring = "?";
-
- for ( key in params ) {
- if ( !hasOwn.call( params, key ) ) {
- continue;
- }
- querystring += encodeURIComponent( key ) + "=" +
- encodeURIComponent( params[ key ] ) + "&";
- }
- return window.location.protocol + "//" + window.location.host +
- window.location.pathname + querystring.slice( 0, -1 );
- },
-
- extend: extend,
- id: id,
- addEvent: addEvent
- // load, equiv, jsDump, diff: Attached later
-});
-
-/**
- * @deprecated: Created for backwards compatibility with test runner that set the hook function
- * into QUnit.{hook}, instead of invoking it and passing the hook function.
- * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
- * Doing this allows us to tell if the following methods have been overwritten on the actual
- * QUnit object.
- */
-extend( QUnit.constructor.prototype, {
-
- // Logging callbacks; all receive a single argument with the listed properties
- // run test/logs.html for any related changes
- begin: registerLoggingCallback( "begin" ),
-
- // done: { failed, passed, total, runtime }
- done: registerLoggingCallback( "done" ),
-
- // log: { result, actual, expected, message }
- log: registerLoggingCallback( "log" ),
-
- // testStart: { name }
- testStart: registerLoggingCallback( "testStart" ),
-
- // testDone: { name, failed, passed, total, duration }
- testDone: registerLoggingCallback( "testDone" ),
-
- // moduleStart: { name }
- moduleStart: registerLoggingCallback( "moduleStart" ),
-
- // moduleDone: { name, failed, passed, total }
- moduleDone: registerLoggingCallback( "moduleDone" )
-});
-
-if ( typeof document === "undefined" || document.readyState === "complete" ) {
- config.autorun = true;
-}
-
-QUnit.load = function() {
- runLoggingCallbacks( "begin", QUnit, {} );
-
- // Initialize the config, saving the execution queue
- var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
- urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
- numModules = 0,
- moduleFilterHtml = "",
- urlConfigHtml = "",
- oldconfig = extend( {}, config );
-
- QUnit.init();
- extend(config, oldconfig);
-
- config.blocking = false;
-
- len = config.urlConfig.length;
-
- for ( i = 0; i < len; i++ ) {
- val = config.urlConfig[i];
- if ( typeof val === "string" ) {
- val = {
- id: val,
- label: val,
- tooltip: "[no tooltip available]"
- };
- }
- config[ val.id ] = QUnit.urlParams[ val.id ];
- urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
- "' name='" + escapeText( val.id ) +
- "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
- " title='" + escapeText( val.tooltip ) +
- "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
- "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
- }
-
- moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
- ( config.module === undefined ? "selected='selected'" : "" ) +
- ">< All Modules ></option>";
-
- for ( i in config.modules ) {
- if ( config.modules.hasOwnProperty( i ) ) {
- numModules += 1;
- moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
- ( config.module === i ? "selected='selected'" : "" ) +
- ">" + escapeText(i) + "</option>";
- }
- }
- moduleFilterHtml += "</select>";
-
- // `userAgent` initialized at top of scope
- userAgent = id( "qunit-userAgent" );
- if ( userAgent ) {
- userAgent.innerHTML = navigator.userAgent;
- }
-
- // `banner` initialized at top of scope
- banner = id( "qunit-header" );
- if ( banner ) {
- banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
- }
-
- // `toolbar` initialized at top of scope
- toolbar = id( "qunit-testrunner-toolbar" );
- if ( toolbar ) {
- // `filter` initialized at top of scope
- filter = document.createElement( "input" );
- filter.type = "checkbox";
- filter.id = "qunit-filter-pass";
-
- addEvent( filter, "click", function() {
- var tmp,
- ol = document.getElementById( "qunit-tests" );
-
- if ( filter.checked ) {
- ol.className = ol.className + " hidepass";
- } else {
- tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
- ol.className = tmp.replace( / hidepass /, " " );
- }
- if ( defined.sessionStorage ) {
- if (filter.checked) {
- sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
- } else {
- sessionStorage.removeItem( "qunit-filter-passed-tests" );
- }
- }
- });
-
- if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
- filter.checked = true;
- // `ol` initialized at top of scope
- ol = document.getElementById( "qunit-tests" );
- ol.className = ol.className + " hidepass";
- }
- toolbar.appendChild( filter );
-
- // `label` initialized at top of scope
- label = document.createElement( "label" );
- label.setAttribute( "for", "qunit-filter-pass" );
- label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
- label.innerHTML = "Hide passed tests";
- toolbar.appendChild( label );
-
- urlConfigCheckboxesContainer = document.createElement("span");
- urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
- urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
- // For oldIE support:
- // * Add handlers to the individual elements instead of the container
- // * Use "click" instead of "change"
- // * Fallback from event.target to event.srcElement
- addEvents( urlConfigCheckboxes, "click", function( event ) {
- var params = {},
- target = event.target || event.srcElement;
- params[ target.name ] = target.checked ? true : undefined;
- window.location = QUnit.url( params );
- });
- toolbar.appendChild( urlConfigCheckboxesContainer );
-
- if (numModules > 1) {
- moduleFilter = document.createElement( 'span' );
- moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
- moduleFilter.innerHTML = moduleFilterHtml;
- addEvent( moduleFilter.lastChild, "change", function() {
- var selectBox = moduleFilter.getElementsByTagName("select")[0],
- selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
-
- window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
- });
- toolbar.appendChild(moduleFilter);
- }
- }
-
- // `main` initialized at top of scope
- main = id( "qunit-fixture" );
- if ( main ) {
- config.fixture = main.innerHTML;
- }
-
- if ( config.autostart ) {
- QUnit.start();
- }
-};
-
-addEvent( window, "load", QUnit.load );
-
-// `onErrorFnPrev` initialized at top of scope
-// Preserve other handlers
-onErrorFnPrev = window.onerror;
-
-// Cover uncaught exceptions
-// Returning true will surpress the default browser handler,
-// returning false will let it run.
-window.onerror = function ( error, filePath, linerNr ) {
- var ret = false;
- if ( onErrorFnPrev ) {
- ret = onErrorFnPrev( error, filePath, linerNr );
- }
-
- // Treat return value as window.onerror itself does,
- // Only do our handling if not surpressed.
- if ( ret !== true ) {
- if ( QUnit.config.current ) {
- if ( QUnit.config.current.ignoreGlobalErrors ) {
- return true;
- }
- QUnit.pushFailure( error, filePath + ":" + linerNr );
- } else {
- QUnit.test( "global failure", extend( function() {
- QUnit.pushFailure( error, filePath + ":" + linerNr );
- }, { validTest: validTest } ) );
- }
- return false;
- }
-
- return ret;
-};
-
-function done() {
- config.autorun = true;
-
- // Log the last module results
- if ( config.currentModule ) {
- runLoggingCallbacks( "moduleDone", QUnit, {
- name: config.currentModule,
- failed: config.moduleStats.bad,
- passed: config.moduleStats.all - config.moduleStats.bad,
- total: config.moduleStats.all
- });
- }
-
- var i, key,
- banner = id( "qunit-banner" ),
- tests = id( "qunit-tests" ),
- runtime = +new Date() - config.started,
- passed = config.stats.all - config.stats.bad,
- html = [
- "Tests completed in ",
- runtime,
- " milliseconds.<br/>",
- "<span class='passed'>",
- passed,
- "</span> assertions of <span class='total'>",
- config.stats.all,
- "</span> passed, <span class='failed'>",
- config.stats.bad,
- "</span> failed."
- ].join( "" );
-
- if ( banner ) {
- banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
- }
-
- if ( tests ) {
- id( "qunit-testresult" ).innerHTML = html;
- }
-
- if ( config.altertitle && typeof document !== "undefined" && document.title ) {
- // show ✖ for good, ✔ for bad suite result in title
- // use escape sequences in case file gets loaded with non-utf-8-charset
- document.title = [
- ( config.stats.bad ? "\u2716" : "\u2714" ),
- document.title.replace( /^[\u2714\u2716] /i, "" )
- ].join( " " );
- }
-
- // clear own sessionStorage items if all tests passed
- if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
- // `key` & `i` initialized at top of scope
- for ( i = 0; i < sessionStorage.length; i++ ) {
- key = sessionStorage.key( i++ );
- if ( key.indexOf( "qunit-test-" ) === 0 ) {
- sessionStorage.removeItem( key );
- }
- }
- }
-
- // scroll back to top to show results
- if ( window.scrollTo ) {
- window.scrollTo(0, 0);
- }
-
- runLoggingCallbacks( "done", QUnit, {
- failed: config.stats.bad,
- passed: passed,
- total: config.stats.all,
- runtime: runtime
- });
-}
-
-/** @return Boolean: true if this test should be ran */
-function validTest( test ) {
- var include,
- filter = config.filter && config.filter.toLowerCase(),
- module = config.module && config.module.toLowerCase(),
- fullName = (test.module + ": " + test.testName).toLowerCase();
-
- // Internally-generated tests are always valid
- if ( test.callback && test.callback.validTest === validTest ) {
- delete test.callback.validTest;
- return true;
- }
-
- if ( config.testNumber ) {
- return test.testNumber === config.testNumber;
- }
-
- if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
- return false;
- }
-
- if ( !filter ) {
- return true;
- }
-
- include = filter.charAt( 0 ) !== "!";
- if ( !include ) {
- filter = filter.slice( 1 );
- }
-
- // If the filter matches, we need to honour include
- if ( fullName.indexOf( filter ) !== -1 ) {
- return include;
- }
-
- // Otherwise, do the opposite
- return !include;
-}
-
-// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
-// Later Safari and IE10 are supposed to support error.stack as well
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
- offset = offset === undefined ? 3 : offset;
-
- var stack, include, i;
-
- if ( e.stacktrace ) {
- // Opera
- return e.stacktrace.split( "\n" )[ offset + 3 ];
- } else if ( e.stack ) {
- // Firefox, Chrome
- stack = e.stack.split( "\n" );
- if (/^error$/i.test( stack[0] ) ) {
- stack.shift();
- }
- if ( fileName ) {
- include = [];
- for ( i = offset; i < stack.length; i++ ) {
- if ( stack[ i ].indexOf( fileName ) !== -1 ) {
- break;
- }
- include.push( stack[ i ] );
- }
- if ( include.length ) {
- return include.join( "\n" );
- }
- }
- return stack[ offset ];
- } else if ( e.sourceURL ) {
- // Safari, PhantomJS
- // hopefully one day Safari provides actual stacktraces
- // exclude useless self-reference for generated Error objects
- if ( /qunit.js$/.test( e.sourceURL ) ) {
- return;
- }
- // for actual exceptions, this is useful
- return e.sourceURL + ":" + e.line;
- }
-}
-function sourceFromStacktrace( offset ) {
- try {
- throw new Error();
- } catch ( e ) {
- return extractStacktrace( e, offset );
- }
-}
-
-/**
- * Escape text for attribute or text content.
- */
-function escapeText( s ) {
- if ( !s ) {
- return "";
- }
- s = s + "";
- // Both single quotes and double quotes (for attributes)
- return s.replace( /['"<>&]/g, function( s ) {
- switch( s ) {
- case '\'':
- return '&#039;';
- case '"':
- return '&quot;';
- case '<':
- return '&lt;';
- case '>':
- return '&gt;';
- case '&':
- return '&amp;';
- }
- });
-}
-
-function synchronize( callback, last ) {
- config.queue.push( callback );
-
- if ( config.autorun && !config.blocking ) {
- process( last );
- }
-}
-
-function process( last ) {
- function next() {
- process( last );
- }
- var start = new Date().getTime();
- config.depth = config.depth ? config.depth + 1 : 1;
-
- while ( config.queue.length && !config.blocking ) {
- if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
- config.queue.shift()();
- } else {
- window.setTimeout( next, 13 );
- break;
- }
- }
- config.depth--;
- if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
- done();
- }
-}
-
-function saveGlobal() {
- config.pollution = [];
-
- if ( config.noglobals ) {
- for ( var key in window ) {
- // in Opera sometimes DOM element ids show up here, ignore them
- if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) {
- continue;
- }
- config.pollution.push( key );
- }
- }
-}
-
-function checkPollution() {
- var newGlobals,
- deletedGlobals,
- old = config.pollution;
-
- saveGlobal();
-
- newGlobals = diff( config.pollution, old );
- if ( newGlobals.length > 0 ) {
- QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
- }
-
- deletedGlobals = diff( old, config.pollution );
- if ( deletedGlobals.length > 0 ) {
- QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
- }
-}
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
- var i, j,
- result = a.slice();
-
- for ( i = 0; i < result.length; i++ ) {
- for ( j = 0; j < b.length; j++ ) {
- if ( result[i] === b[j] ) {
- result.splice( i, 1 );
- i--;
- break;
- }
- }
- }
- return result;
-}
-
-function extend( a, b ) {
- for ( var prop in b ) {
- if ( b[ prop ] === undefined ) {
- delete a[ prop ];
-
- // Avoid "Member not found" error in IE8 caused by setting window.constructor
- } else if ( prop !== "constructor" || a !== window ) {
- a[ prop ] = b[ prop ];
- }
- }
-
- return a;
-}
-
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
- // Standards-based browsers
- if ( elem.addEventListener ) {
- elem.addEventListener( type, fn, false );
- // IE
- } else {
- elem.attachEvent( "on" + type, fn );
- }
-}
-
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
- var i = elems.length;
- while ( i-- ) {
- addEvent( elems[i], type, fn );
- }
-}
-
-function hasClass( elem, name ) {
- return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
-}
-
-function addClass( elem, name ) {
- if ( !hasClass( elem, name ) ) {
- elem.className += (elem.className ? " " : "") + name;
- }
-}
-
-function removeClass( elem, name ) {
- var set = " " + elem.className + " ";
- // Class name may appear multiple times
- while ( set.indexOf(" " + name + " ") > -1 ) {
- set = set.replace(" " + name + " " , " ");
- }
- // If possible, trim it for prettiness, but not neccecarily
- elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
-}
-
-function id( name ) {
- return !!( typeof document !== "undefined" && document && document.getElementById ) &&
- document.getElementById( name );
-}
-
-function registerLoggingCallback( key ) {
- return function( callback ) {
- config[key].push( callback );
- };
-}
-
-// Supports deprecated method of completely overwriting logging callbacks
-function runLoggingCallbacks( key, scope, args ) {
- var i, callbacks;
- if ( QUnit.hasOwnProperty( key ) ) {
- QUnit[ key ].call(scope, args );
- } else {
- callbacks = config[ key ];
- for ( i = 0; i < callbacks.length; i++ ) {
- callbacks[ i ].call( scope, args );
- }
- }
-}
-
-// Test for equality any JavaScript type.
-// Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = (function() {
-
- // Call the o related callback with the given arguments.
- function bindCallbacks( o, callbacks, args ) {
- var prop = QUnit.objectType( o );
- if ( prop ) {
- if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
- return callbacks[ prop ].apply( callbacks, args );
- } else {
- return callbacks[ prop ]; // or undefined
- }
- }
- }
-
- // the real equiv function
- var innerEquiv,
- // stack to decide between skip/abort functions
- callers = [],
- // stack to avoiding loops from circular referencing
- parents = [],
-
- getProto = Object.getPrototypeOf || function ( obj ) {
- return obj.__proto__;
- },
- callbacks = (function () {
-
- // for string, boolean, number and null
- function useStrictEquality( b, a ) {
- /*jshint eqeqeq:false */
- if ( b instanceof a.constructor || a instanceof b.constructor ) {
- // to catch short annotaion VS 'new' annotation of a
- // declaration
- // e.g. var i = 1;
- // var j = new Number(1);
- return a == b;
- } else {
- return a === b;
- }
- }
-
- return {
- "string": useStrictEquality,
- "boolean": useStrictEquality,
- "number": useStrictEquality,
- "null": useStrictEquality,
- "undefined": useStrictEquality,
-
- "nan": function( b ) {
- return isNaN( b );
- },
-
- "date": function( b, a ) {
- return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
- },
-
- "regexp": function( b, a ) {
- return QUnit.objectType( b ) === "regexp" &&
- // the regex itself
- a.source === b.source &&
- // and its modifers
- a.global === b.global &&
- // (gmi) ...
- a.ignoreCase === b.ignoreCase &&
- a.multiline === b.multiline &&
- a.sticky === b.sticky;
- },
-
- // - skip when the property is a method of an instance (OOP)
- // - abort otherwise,
- // initial === would have catch identical references anyway
- "function": function() {
- var caller = callers[callers.length - 1];
- return caller !== Object && typeof caller !== "undefined";
- },
-
- "array": function( b, a ) {
- var i, j, len, loop;
-
- // b could be an object literal here
- if ( QUnit.objectType( b ) !== "array" ) {
- return false;
- }
-
- len = a.length;
- if ( len !== b.length ) {
- // safe and faster
- return false;
- }
-
- // track reference to avoid circular references
- parents.push( a );
- for ( i = 0; i < len; i++ ) {
- loop = false;
- for ( j = 0; j < parents.length; j++ ) {
- if ( parents[j] === a[i] ) {
- loop = true;// dont rewalk array
- }
- }
- if ( !loop && !innerEquiv(a[i], b[i]) ) {
- parents.pop();
- return false;
- }
- }
- parents.pop();
- return true;
- },
-
- "object": function( b, a ) {
- var i, j, loop,
- // Default to true
- eq = true,
- aProperties = [],
- bProperties = [];
-
- // comparing constructors is more strict than using
- // instanceof
- if ( a.constructor !== b.constructor ) {
- // Allow objects with no prototype to be equivalent to
- // objects with Object as their constructor.
- if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
- ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
- return false;
- }
- }
-
- // stack constructor before traversing properties
- callers.push( a.constructor );
- // track reference to avoid circular references
- parents.push( a );
-
- for ( i in a ) { // be strict: don't ensures hasOwnProperty
- // and go deep
- loop = false;
- for ( j = 0; j < parents.length; j++ ) {
- if ( parents[j] === a[i] ) {
- // don't go down the same path twice
- loop = true;
- }
- }
- aProperties.push(i); // collect a's properties
-
- if (!loop && !innerEquiv( a[i], b[i] ) ) {
- eq = false;
- break;
- }
- }
-
- callers.pop(); // unstack, we are done
- parents.pop();
-
- for ( i in b ) {
- bProperties.push( i ); // collect b's properties
- }
-
- // Ensures identical properties name
- return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
- }
- };
- }());
-
- innerEquiv = function() { // can take multiple arguments
- var args = [].slice.apply( arguments );
- if ( args.length < 2 ) {
- return true; // end transition
- }
-
- return (function( a, b ) {
- if ( a === b ) {
- return true; // catch the most you can
- } else if ( a === null || b === null || typeof a === "undefined" ||
- typeof b === "undefined" ||
- QUnit.objectType(a) !== QUnit.objectType(b) ) {
- return false; // don't lose time with error prone cases
- } else {
- return bindCallbacks(a, callbacks, [ b, a ]);
- }
-
- // apply transition with (1..n) arguments
- }( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) );
- };
-
- return innerEquiv;
-}());
-
-/**
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
- * http://flesler.blogspot.com Licensed under BSD
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
- *
- * @projectDescription Advanced and extensible data dumping for Javascript.
- * @version 1.0.0
- * @author Ariel Flesler
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
- */
-QUnit.jsDump = (function() {
- function quote( str ) {
- return '"' + str.toString().replace( /"/g, '\\"' ) + '"';
- }
- function literal( o ) {
- return o + "";
- }
- function join( pre, arr, post ) {
- var s = jsDump.separator(),
- base = jsDump.indent(),
- inner = jsDump.indent(1);
- if ( arr.join ) {
- arr = arr.join( "," + s + inner );
- }
- if ( !arr ) {
- return pre + post;
- }
- return [ pre, inner + arr, base + post ].join(s);
- }
- function array( arr, stack ) {
- var i = arr.length, ret = new Array(i);
- this.up();
- while ( i-- ) {
- ret[i] = this.parse( arr[i] , undefined , stack);
- }
- this.down();
- return join( "[", ret, "]" );
- }
-
- var reName = /^function (\w+)/,
- jsDump = {
- // type is used mostly internally, you can fix a (custom)type in advance
- parse: function( obj, type, stack ) {
- stack = stack || [ ];
- var inStack, res,
- parser = this.parsers[ type || this.typeOf(obj) ];
-
- type = typeof parser;
- inStack = inArray( obj, stack );
-
- if ( inStack !== -1 ) {
- return "recursion(" + (inStack - stack.length) + ")";
- }
- if ( type === "function" ) {
- stack.push( obj );
- res = parser.call( this, obj, stack );
- stack.pop();
- return res;
- }
- return ( type === "string" ) ? parser : this.parsers.error;
- },
- typeOf: function( obj ) {
- var type;
- if ( obj === null ) {
- type = "null";
- } else if ( typeof obj === "undefined" ) {
- type = "undefined";
- } else if ( QUnit.is( "regexp", obj) ) {
- type = "regexp";
- } else if ( QUnit.is( "date", obj) ) {
- type = "date";
- } else if ( QUnit.is( "function", obj) ) {
- type = "function";
- } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
- type = "window";
- } else if ( obj.nodeType === 9 ) {
- type = "document";
- } else if ( obj.nodeType ) {
- type = "node";
- } else if (
- // native arrays
- toString.call( obj ) === "[object Array]" ||
- // NodeList objects
- ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
- ) {
- type = "array";
- } else if ( obj.constructor === Error.prototype.constructor ) {
- type = "error";
- } else {
- type = typeof obj;
- }
- return type;
- },
- separator: function() {
- return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
- },
- // extra can be a number, shortcut for increasing-calling-decreasing
- indent: function( extra ) {
- if ( !this.multiline ) {
- return "";
- }
- var chr = this.indentChar;
- if ( this.HTML ) {
- chr = chr.replace( /\t/g, " " ).replace( / /g, "&nbsp;" );
- }
- return new Array( this._depth_ + (extra||0) ).join(chr);
- },
- up: function( a ) {
- this._depth_ += a || 1;
- },
- down: function( a ) {
- this._depth_ -= a || 1;
- },
- setParser: function( name, parser ) {
- this.parsers[name] = parser;
- },
- // The next 3 are exposed so you can use them
- quote: quote,
- literal: literal,
- join: join,
- //
- _depth_: 1,
- // This is the list of parsers, to modify them, use jsDump.setParser
- parsers: {
- window: "[Window]",
- document: "[Document]",
- error: function(error) {
- return "Error(\"" + error.message + "\")";
- },
- unknown: "[Unknown]",
- "null": "null",
- "undefined": "undefined",
- "function": function( fn ) {
- var ret = "function",
- // functions never have name in IE
- name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
-
- if ( name ) {
- ret += " " + name;
- }
- ret += "( ";
-
- ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
- return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
- },
- array: array,
- nodelist: array,
- "arguments": array,
- object: function( map, stack ) {
- var ret = [ ], keys, key, val, i;
- QUnit.jsDump.up();
- keys = [];
- for ( key in map ) {
- keys.push( key );
- }
- keys.sort();
- for ( i = 0; i < keys.length; i++ ) {
- key = keys[ i ];
- val = map[ key ];
- ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
- }
- QUnit.jsDump.down();
- return join( "{", ret, "}" );
- },
- node: function( node ) {
- var len, i, val,
- open = QUnit.jsDump.HTML ? "&lt;" : "<",
- close = QUnit.jsDump.HTML ? "&gt;" : ">",
- tag = node.nodeName.toLowerCase(),
- ret = open + tag,
- attrs = node.attributes;
-
- if ( attrs ) {
- for ( i = 0, len = attrs.length; i < len; i++ ) {
- val = attrs[i].nodeValue;
- // IE6 includes all attributes in .attributes, even ones not explicitly set.
- // Those have values like undefined, null, 0, false, "" or "inherit".
- if ( val && val !== "inherit" ) {
- ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
- }
- }
- }
- ret += close;
-
- // Show content of TextNode or CDATASection
- if ( node.nodeType === 3 || node.nodeType === 4 ) {
- ret += node.nodeValue;
- }
-
- return ret + open + "/" + tag + close;
- },
- // function calls it internally, it's the arguments part of the function
- functionArgs: function( fn ) {
- var args,
- l = fn.length;
-
- if ( !l ) {
- return "";
- }
-
- args = new Array(l);
- while ( l-- ) {
- // 97 is 'a'
- args[l] = String.fromCharCode(97+l);
- }
- return " " + args.join( ", " ) + " ";
- },
- // object calls it internally, the key part of an item in a map
- key: quote,
- // function calls it internally, it's the content of the function
- functionCode: "[code]",
- // node calls it internally, it's an html attribute value
- attribute: quote,
- string: quote,
- date: quote,
- regexp: literal,
- number: literal,
- "boolean": literal
- },
- // if true, entities are escaped ( <, >, \t, space and \n )
- HTML: false,
- // indentation unit
- indentChar: " ",
- // if true, items in a collection, are separated by a \n, else just a space.
- multiline: true
- };
-
- return jsDump;
-}());
-
-// from jquery.js
-function inArray( elem, array ) {
- if ( array.indexOf ) {
- return array.indexOf( elem );
- }
-
- for ( var i = 0, length = array.length; i < length; i++ ) {
- if ( array[ i ] === elem ) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * Javascript Diff Algorithm
- * By John Resig (http://ejohn.org/)
- * Modified by Chu Alan "sprite"
- *
- * Released under the MIT license.
- *
- * More Info:
- * http://ejohn.org/projects/javascript-diff-algorithm/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
- */
-QUnit.diff = (function() {
- /*jshint eqeqeq:false, eqnull:true */
- function diff( o, n ) {
- var i,
- ns = {},
- os = {};
-
- for ( i = 0; i < n.length; i++ ) {
- if ( !hasOwn.call( ns, n[i] ) ) {
- ns[ n[i] ] = {
- rows: [],
- o: null
- };
- }
- ns[ n[i] ].rows.push( i );
- }
-
- for ( i = 0; i < o.length; i++ ) {
- if ( !hasOwn.call( os, o[i] ) ) {
- os[ o[i] ] = {
- rows: [],
- n: null
- };
- }
- os[ o[i] ].rows.push( i );
- }
-
- for ( i in ns ) {
- if ( !hasOwn.call( ns, i ) ) {
- continue;
- }
- if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
- n[ ns[i].rows[0] ] = {
- text: n[ ns[i].rows[0] ],
- row: os[i].rows[0]
- };
- o[ os[i].rows[0] ] = {
- text: o[ os[i].rows[0] ],
- row: ns[i].rows[0]
- };
- }
- }
-
- for ( i = 0; i < n.length - 1; i++ ) {
- if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
- n[ i + 1 ] == o[ n[i].row + 1 ] ) {
-
- n[ i + 1 ] = {
- text: n[ i + 1 ],
- row: n[i].row + 1
- };
- o[ n[i].row + 1 ] = {
- text: o[ n[i].row + 1 ],
- row: i + 1
- };
- }
- }
-
- for ( i = n.length - 1; i > 0; i-- ) {
- if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
- n[ i - 1 ] == o[ n[i].row - 1 ]) {
-
- n[ i - 1 ] = {
- text: n[ i - 1 ],
- row: n[i].row - 1
- };
- o[ n[i].row - 1 ] = {
- text: o[ n[i].row - 1 ],
- row: i - 1
- };
- }
- }
-
- return {
- o: o,
- n: n
- };
- }
-
- return function( o, n ) {
- o = o.replace( /\s+$/, "" );
- n = n.replace( /\s+$/, "" );
-
- var i, pre,
- str = "",
- out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
- oSpace = o.match(/\s+/g),
- nSpace = n.match(/\s+/g);
-
- if ( oSpace == null ) {
- oSpace = [ " " ];
- }
- else {
- oSpace.push( " " );
- }
-
- if ( nSpace == null ) {
- nSpace = [ " " ];
- }
- else {
- nSpace.push( " " );
- }
-
- if ( out.n.length === 0 ) {
- for ( i = 0; i < out.o.length; i++ ) {
- str += "<del>" + out.o[i] + oSpace[i] + "</del>";
- }
- }
- else {
- if ( out.n[0].text == null ) {
- for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
- str += "<del>" + out.o[n] + oSpace[n] + "</del>";
- }
- }
-
- for ( i = 0; i < out.n.length; i++ ) {
- if (out.n[i].text == null) {
- str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
- }
- else {
- // `pre` initialized at top of scope
- pre = "";
-
- for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
- pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
- }
- str += " " + out.n[i].text + nSpace[i] + pre;
- }
- }
- }
-
- return str;
- };
-}());
-
-// for CommonJS enviroments, export everything
-if ( typeof exports !== "undefined" ) {
- extend( exports, QUnit );
-}
-
-// get at whatever the global object is, like window in browsers
-}( (function() {return this;}.call()) ));