Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | 1x 1x 1x 50x 3x 50x 4x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 46x 138x 46x 46x 40x 46x 46x 46x 41x 46x 37x 46x 40x 46x 1x 46x 2x 2x 1x 1x 46x 3x 3x 3x 46x 2x 2x 2x 2x 46x 2x 2x 2x 46x 46x 46x 8x 8x 3x 3x 8x 2x 6x 6x 1x 5x 1x 4x 4x 4x 4x 4x 4x 4x 4x 2x 4x 4x 4x 1x 1x 3x 3x 3x 4x 1x 3x | /*! * jQuery Client 3.0.0 * https://gerrit.wikimedia.org/g/jquery-client/ * * Copyright Trevor Parscal, Timo Tijhof, and Roan Kattouw. * Released under the MIT license. */ /** * User-agent detection * * @class jQuery.client * @hideconstructor */ ( function () { /** * @typedef {Object} jQuery.client.Profile An object containing information about the client. * * @property {string|'unknown'} name Name of the browser. Recognized browser names: * - `android` (legacy Android browser, prior to Chrome Mobile) * - `chrome` (includes Chrome Mobile, Microsoft Edge, Opera, and others) * - `crios` (Chrome on iOS, which uses Mobile Safari) * - `edge` (legacy Microsoft Edge, which uses EdgeHTML) * - `firefox` (includes Firefox Mobile, Iceweasel, and others) * - `fxios` (Firefox on iOS, which uses Mobile Safari) * - `konqueror` * - `msie` * - `opera` (legacy Opera, which uses Presto) * - `rekonq` * - `safari` (including Mobile Safari) * - `silk` * * @property {string|'unknown'} layout Name of the layout engine. Recognised layout engines: * * - `edge` (EdgeHTML 12-18, as used by legacy Microsoft Edge) * - `gecko` * - `khtml` * - `presto` * - `trident` * - `webkit` * * Note that Chrome and Chromium-based browsers like Opera have their layout * engine identified as `webkit`. * * @property {number|'unknown'} layoutVersion Version of the layout engine, * e.g. `6` or `20101026`. * * @property {string|'unknown'} platform Operating system the browser is running on. * Recognised platforms: * * - `ipad` * - `iphone` * - `linux` * - `mac` * - `solaris` (untested) * - `win` * * @property {string|'unknown'} version * @property {string|'unknown'} versionBase * @property {number} versionNumber * * @example * { * 'name': 'firefox', * 'layout': 'gecko', * 'layoutVersion': 20101026, * 'platform': 'linux' * 'version': '3.5.1', * 'versionBase': '3', * 'versionNumber': 3.5, * } */ /** * Keyed by the user agent string. * * @private * @type {Object.<string,jQuery.client.Profile>} */ const profileCache = {}; $.client = { /** * Get an object containing information about the client. * * @example * if ( $.client.profile().layout == 'gecko' ) { * // This will only run in Gecko browsers, such as Mozilla Firefox. * } * * var profile = $.client.profile(); * if ( profile.layout == 'gecko' && profile.platform == 'linux' ) { * // This will only run in Gecko browsers on Linux. * } * * @memberof jQuery.client * @param {{userAgent: string, platform: string}} [nav=window.navigator] An object with * a `userAgent` and `platform` property. * @return {jQuery.client.Profile} */ profile: function ( nav ) { if ( !nav ) { nav = window.navigator; } // Use the cached version if possible if ( profileCache[ nav.userAgent + '|' + nav.platform ] ) { return profileCache[ nav.userAgent + '|' + nav.platform ]; } const key = nav.userAgent + '|' + nav.platform, // Configuration // Name of browsers or layout engines we don't recognize uk = 'unknown', // Generic version digit x = 'x', // Fixups for user agent strings that contain wild words wildFixups = [ // Chrome lives in the shadow of Safari still [ 'Chrome Safari', 'Chrome' ], // KHTML is the layout engine not the browser - LIES! [ 'KHTML/', 'Konqueror/' ], // For Firefox Mobile, strip out "Android;" or "Android [version]" so that we // classify it as Firefox instead of Android (default browser) [ /Android(?:;|\s[a-zA-Z0-9.+-]+)(.*Firefox)/, '$1' ] ], // Strings which precede a version number in a user agent string versionPrefixes = '(?:chrome|crios|firefox|fxios|opera|version|konqueror|msie|safari|android)', // This matches the actual version number, with non-capturing groups for the // separator and suffix versionSuffix = '(?:\\/|;?\\s|)([a-z0-9\\.\\+]*?)(?:;|dev|rel|\\)|\\s|$)', // Match the names of known browser families rName = /(chrome|crios|firefox|fxios|konqueror|msie|opera|safari|rekonq|android)/, // Match the name of known layout engines rLayout = /(gecko|konqueror|msie|trident|edge|opera|webkit)/, // Translations for conforming layout names layoutMap = { konqueror: 'khtml', msie: 'trident', opera: 'presto' }, // Match the prefix and version of supported layout engines rLayoutVersion = /(applewebkit|gecko|trident|edge)\/(\d+)/, // Match the name of known operating systems rPlatform = /(win|wow64|mac|linux|sunos|solaris|iphone|ipad)/, // Translations for conforming operating system names platformMap = { sunos: 'solaris', wow64: 'win' }; // Pre-processing let ua = nav.userAgent, match, name = uk, layout = uk, layoutversion = uk, platform = uk, version = x; // Takes a userAgent string and fixes it into something we can more // easily work with wildFixups.forEach( ( fixup ) => { ua = ua.replace( fixup[ 0 ], fixup[ 1 ] ); } ); // Everything will be in lowercase from now on ua = ua.toLowerCase(); // Extraction if ( ( match = rName.exec( ua ) ) ) { name = match[ 1 ]; } Eif ( ( match = rLayout.exec( ua ) ) ) { layout = layoutMap[ match[ 1 ] ] || match[ 1 ]; } if ( ( match = rLayoutVersion.exec( ua ) ) ) { layoutversion = parseInt( match[ 2 ], 10 ); } if ( ( match = rPlatform.exec( nav.platform.toLowerCase() ) ) ) { platform = platformMap[ match[ 1 ] ] || match[ 1 ]; } if ( ( match = new RegExp( versionPrefixes + versionSuffix ).exec( ua ) ) ) { version = match[ 1 ]; } // Edge Cases -- did I mention about how user agent string lie? // Decode Safari's crazy 400+ version numbers if ( name === 'safari' && version > 400 ) { version = '2.0'; } // Expose Opera 10's lies about being Opera 9.8 if ( name === 'opera' && version >= 9.8 ) { match = ua.match( /\bversion\/([0-9.]*)/ ); if ( match && match[ 1 ] ) { version = match[ 1 ]; } else { version = '10'; } } // And IE 11's lies about being not being IE if ( layout === 'trident' && layoutversion >= 7 && ( match = ua.match( /\brv[ :/]([0-9.]*)/ ) ) ) { Eif ( match[ 1 ] ) { name = 'msie'; version = match[ 1 ]; } } // And MS Edge's lies about being Chrome // // It's different enough from classic IE Trident engine that they do this // to avoid getting caught by MSIE-specific browser sniffing. if ( name === 'chrome' && ( match = ua.match( /\bedge\/([0-9.]*)/ ) ) ) { name = 'edge'; version = match[ 1 ]; layout = 'edge'; layoutversion = parseInt( match[ 1 ], 10 ); } // And Amazon Silk's lies about being Android on mobile or Safari on desktop if ( ( match = ua.match( /\bsilk\/([0-9.\-_]*)/ ) ) ) { Eif ( match[ 1 ] ) { name = 'silk'; version = match[ 1 ]; } } const versionNumber = parseFloat( version, 10 ) || 0.0; // Caching profileCache[ key ] = { name: name, layout: layout, layoutVersion: layoutversion, platform: platform, version: version, versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ), versionNumber: versionNumber }; return profileCache[ key ]; }, /** * Checks the current browser against a support map object. * * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11). * Version numbers passed as string values will be compared using a simple component-wise * algorithm, similar to PHP's version_compare ('1.2' < '1.11'). * * A browser map is in the following format: * * { * // Multiple rules with configurable operators * 'msie': [['>=', 7], ['!=', 9]], * // Match no versions * 'iphone': false, * // Match any version * 'android': null * } * * It can optionally be split into ltr/rtl sections: * * { * 'ltr': { * 'android': null, * 'iphone': false * }, * 'rtl': { * 'android': false, * // rules are not inherited from ltr * 'iphone': false * } * } * * @memberof jQuery.client * @param {Object} map Browser support map * @param {jQuery.client.Profile} [profile] A client-profile object * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, * otherwise returns true if the browser is not found. * * @return {boolean} The current browser is in the support map */ test: function ( map, profile, exactMatchOnly ) { profile = $.isPlainObject( profile ) ? profile : $.client.profile(); if ( map.ltr && map.rtl ) { const dir = $( document.body ).is( '.rtl' ) ? 'rtl' : 'ltr'; map = map[ dir ]; } // Check over each browser condition to determine if we are running in a // compatible client if ( typeof map !== 'object' || map[ profile.name ] === undefined ) { // Not found, return true if exactMatchOnly not set, false otherwise return !exactMatchOnly; } const conditions = map[ profile.name ]; if ( conditions === false ) { // Match no versions return false; } if ( conditions === null ) { // Match all versions return true; } for ( let i = 0; i < conditions.length; i++ ) { const op = conditions[ i ][ 0 ]; const val = conditions[ i ][ 1 ]; if ( typeof val === 'string' ) { // Perform a component-wise comparison of versions, similar to // PHP's version_compare but simpler. '1.11' is larger than '1.2'. const pieceVersion = profile.version.toString().split( '.' ); const pieceVal = val.split( '.' ); // Extend with zeroes to equal length while ( pieceVersion.length < pieceVal.length ) { pieceVersion.push( '0' ); } while ( pieceVal.length < pieceVersion.length ) { pieceVal.push( '0' ); } // Compare components let compare = 0; for ( let j = 0; j < pieceVersion.length; j++ ) { if ( Number( pieceVersion[ j ] ) < Number( pieceVal[ j ] ) ) { compare = -1; break; } else Eif ( Number( pieceVersion[ j ] ) > Number( pieceVal[ j ] ) ) { compare = 1; break; } } // compare will be -1, 0 or 1, depending on comparison result // eslint-disable-next-line no-eval, security/detect-eval-with-expression if ( !( eval( String( compare + op + '0' ) ) ) ) { return false; } } else Eif ( typeof val === 'number' ) { // eslint-disable-next-line no-eval, security/detect-eval-with-expression if ( !( eval( 'profile.versionNumber' + op + val ) ) ) { return false; } } } return true; } }; }() ); |