diff --git a/dist/jquery.browser.d.ts b/dist/jquery.browser.d.ts index bbd72da..fa4b5a6 100644 --- a/dist/jquery.browser.d.ts +++ b/dist/jquery.browser.d.ts @@ -2,64 +2,65 @@ * Browser detection result interface */ export interface BrowserDetection { - msie?: boolean; - webkit?: boolean; - mozilla?: boolean; - chrome?: boolean; - safari?: boolean; - opr?: boolean; - opera?: boolean; - msedge?: boolean; - edge?: boolean; - rv?: boolean; - iemobile?: boolean; - android?: boolean; - blackberry?: boolean; - cros?: boolean; - ipad?: boolean; - iphone?: boolean; - ipod?: boolean; - kindle?: boolean; - linux?: boolean; - mac?: boolean; - playbook?: boolean; - silk?: boolean; - win?: boolean; - "windows phone"?: boolean; - bb?: boolean; - mobile?: boolean; - desktop?: boolean; - name: string; - version: string; - versionNumber: number; - platform: string; - uaMatch: (ua?: string) => BrowserDetection; + // Browser flags + msie?: boolean; + webkit?: boolean; + mozilla?: boolean; + chrome?: boolean; + safari?: boolean; + opr?: boolean; + opera?: boolean; + msedge?: boolean; + edge?: boolean; + rv?: boolean; + iemobile?: boolean; + + // Platform flags + android?: boolean; + blackberry?: boolean; + cros?: boolean; + ipad?: boolean; + iphone?: boolean; + ipod?: boolean; + kindle?: boolean; + linux?: boolean; + mac?: boolean; + playbook?: boolean; + silk?: boolean; + win?: boolean; + "windows phone"?: boolean; + bb?: boolean; + + // Classification flags + mobile?: boolean; + desktop?: boolean; + + // Metadata + name: string; + version: string; + versionNumber: number; + platform: string; + + // Function to match arbitrary user agents + uaMatch: (ua?: string) => BrowserDetection; } + /** * jQuery interface extension */ interface JQueryStatic { - browser: BrowserDetection; + browser: BrowserDetection; } + /** * Global window interface extension */ declare global { - interface Window { - jQBrowser: BrowserDetection; - jQuery?: JQueryStatic; - } + interface Window { + jQBrowser: BrowserDetection; + jQuery?: JQueryStatic; + } } -/** - * Matches a user agent string and returns browser detection information - * @param ua - Optional user agent string. If not provided, uses navigator.userAgent - * @returns Browser detection object - */ -declare function uaMatch(ua?: string): BrowserDetection; -/** - * Factory function for module systems (AMD, CommonJS, Browser globals) - */ -declare function factory(jQuery?: JQueryStatic): BrowserDetection; -export { uaMatch, factory }; -export default factory; -//# sourceMappingURL=jquery.browser.d.ts.map \ No newline at end of file + +export {}; + diff --git a/dist/jquery.browser.d.ts.map b/dist/jquery.browser.d.ts.map deleted file mode 100644 index c017d12..0000000 --- a/dist/jquery.browser.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jquery.browser.d.ts","sourceRoot":"","sources":["../src/jquery.browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IAGb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IAGjB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC5C;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,SAAS,EAAE,gBAAgB,CAAC;QAC5B,MAAM,CAAC,EAAE,YAAY,CAAC;KACvB;CACF;AAED;;;;GAIG;AACH,iBAAS,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAwK9C;AAED;;GAEG;AACH,iBAAS,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAmBxD;AA8CD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC5B,eAAe,OAAO,CAAC"} \ No newline at end of file diff --git a/dist/jquery.browser.js b/dist/jquery.browser.js index 43b923d..93edad8 100644 --- a/dist/jquery.browser.js +++ b/dist/jquery.browser.js @@ -1,152 +1,386 @@ -/*!\n * jQuery Browser Plugin \n * https://github.com/melloware/jquery-browser-plugin\n *\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\n * http://jquery.org/license\n *\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\n * https://github.com/melloware\n *\n * Released under the MIT license\n */ -"use strict"; -var jQBrowser = (() => { - var __defProp = Object.defineProperty; - var __getOwnPropDesc = Object.getOwnPropertyDescriptor; - var __getOwnPropNames = Object.getOwnPropertyNames; - var __hasOwnProp = Object.prototype.hasOwnProperty; - var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { - get: (a, b) => (typeof require !== "undefined" ? require : a)[b] - }) : x)(function(x) { - if (typeof require !== "undefined") return require.apply(this, arguments); - throw Error('Dynamic require of "' + x + '" is not supported'); - }); - var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); - }; - var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; - }; - var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - - // src/jquery.browser.ts - var jquery_browser_exports = {}; - __export(jquery_browser_exports, { - default: () => jquery_browser_default, - factory: () => factory, - uaMatch: () => uaMatch - }); - function uaMatch(ua) { - if (ua === void 0) { - if (typeof window !== "undefined" && window.navigator) { - ua = window.navigator.userAgent; - } else { - ua = ""; - } +/*! + * jQuery Browser Plugin + * https://github.com/melloware/jquery-browser-plugin + * + * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors + * http://jquery.org/license + * + * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware + * https://github.com/melloware + * + * Released under the MIT license + */ +(function (factory) { + + if (typeof define === 'function' && define.amd) { + + // AMD. Register as an anonymous module. + + define(['jquery'], function ($) { + + return factory($); + + }); + + } else if (typeof module === 'object' && typeof module.exports === 'object') { + + // Node-like environment + + module.exports = factory(require('jquery')); + + } else { + + // Browser globals + + factory(window.jQuery); + + } + +}(function(jQuery) { + + "use strict"; + + + + function uaMatch( ua ) { + + // If an UA is not provided, default to the current browser UA. + + if ( ua === undefined ) { + + ua = window.navigator.userAgent; + } + ua = ua.toLowerCase(); - const match = ( - // Chromium Edge (Edg/EdgA/EdgIOS) - must come before Chrome to avoid false positives - /(edg|edga|edgios)\/([\w.]+)/.exec(ua) || // Legacy Edge (EdgeHTML) - must come before Chrome - /(edge)\/([\w.]+)/.exec(ua) || // Opera 15+ (OPR) - must come before Chrome - /(opr)[\/]([\w.]+)/.exec(ua) || // Chrome - must come before Safari - /(chrome)[ \/]([\w.]+)/.exec(ua) || // IE Mobile - /(iemobile)[\/]([\w.]+)/.exec(ua) || // Safari (with version) - specific pattern for Safari - /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || // Safari (alternative pattern) - /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || // WebKit (generic) - catch-all for WebKit browsers - /(webkit)[ \/]([\w.]+)/.exec(ua) || // Opera (legacy Presto engine) - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || // IE (legacy MSIE token) - /(msie) ([\w.]+)/.exec(ua) || // IE 11 (Trident engine with rv: token) - ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua) || // Firefox (Gecko engine, not compatible mode) - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [] - ); - const platform_match = /(ipad)/.exec(ua) || /(ipod)/.exec(ua) || /(windows phone)/.exec(ua) || /(iphone)/.exec(ua) || /(kindle)/.exec(ua) || /(silk)/.exec(ua) || /(android)/.exec(ua) || /(win)/.exec(ua) || /(mac)/.exec(ua) || /(linux)/.exec(ua) || /(cros)/.exec(ua) || /(playbook)/.exec(ua) || /(bb)/.exec(ua) || /(blackberry)/.exec(ua) || []; - const browser = {}; - const browserName = match[1] === "edg" || match[1] === "edga" || match[1] === "edgios" ? "msedge" : match[5] || match[3] || match[1] || ""; - const matched = { - browser: browserName, - version: match[2] || match[4] || "0", - versionNumber: match[4] || match[2] || "0", - platform: platform_match[0] || "" - }; - if (matched.browser) { - browser[matched.browser] = true; + + + + var match = /(edg|edga|edgios)\/([\w.]+)/.exec( ua ) || + + /(edge)\/([\w.]+)/.exec( ua ) || + + /(opr)[\/]([\w.]+)/.exec( ua ) || + + /(chrome)[ \/]([\w.]+)/.exec( ua ) || + + /(iemobile)[\/]([\w.]+)/.exec( ua ) || + + /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( ua ) || + + /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( ua ) || + + /(webkit)[ \/]([\w.]+)/.exec( ua ) || + + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || + + /(msie) ([\w.]+)/.exec( ua ) || + + ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec( ua ) || + + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || + + []; + + + + var platform_match = /(ipad)/.exec( ua ) || + + /(ipod)/.exec( ua ) || + + /(windows phone)/.exec( ua ) || + + /(iphone)/.exec( ua ) || + + /(kindle)/.exec( ua ) || + + /(silk)/.exec( ua ) || + + /(android)/.exec( ua ) || + + /(win)/.exec( ua ) || + + /(mac)/.exec( ua ) || + + /(linux)/.exec( ua ) || + + /(cros)/.exec( ua ) || + + /(playbook)/.exec( ua ) || + + /(bb)/.exec( ua ) || + + /(blackberry)/.exec( ua ) || + + []; + + + + var browser = {}, + + matched = { + + browser: match[ 5 ] || match[ 3 ] || match[ 1 ] || "", + + version: match[ 2 ] || match[ 4 ] || "0", + + versionNumber: match[ 4 ] || match[ 2 ] || "0", + + platform: platform_match[ 0 ] || "" + + }; + + + + // Track if this is Chromium Edge (before normalization) + + var isChromiumEdge = matched.browser === "edg" || matched.browser === "edga" || matched.browser === "edgios"; + + + + // Normalize Chromium Edge (edg/edga/edgios) to msedge + + if ( isChromiumEdge ) { + + matched.browser = "msedge"; + + } + + + + if ( matched.browser ) { + + browser[ matched.browser ] = true; + browser.version = matched.version; + browser.versionNumber = parseInt(matched.versionNumber, 10); + } - if (matched.platform) { - browser[matched.platform] = true; + + + + if ( matched.platform ) { + + browser[ matched.platform ] = true; + } - if (browser.android || browser.bb || browser.blackberry || browser.ipad || browser.iphone || browser.ipod || browser.kindle || browser.playbook || browser.silk || browser["windows phone"]) { + + + + // These are all considered mobile platforms, meaning they run a mobile browser + + if ( browser.android || browser.bb || browser.blackberry || browser.ipad || browser.iphone || + + browser.ipod || browser.kindle || browser.playbook || browser.silk || browser[ "windows phone" ]) { + browser.mobile = true; + } - if (browser.cros || browser.mac || browser.linux || browser.win) { + + + + // These are all considered desktop platforms, meaning they run a desktop browser + + if ( browser.cros || browser.mac || browser.linux || browser.win ) { + browser.desktop = true; + } - if (browser.chrome || browser.opr || browser.safari || browser.msedge) { + + + + // Chrome, Opera 15+, Safari, and Chromium Edge are webkit based browsers + + // Note: Only Chromium Edge (not legacy Edge) is webkit-based + + if ( browser.chrome || browser.opr || browser.safari || ( browser.msedge && isChromiumEdge ) ) { + browser.webkit = true; + } - if (browser.rv || browser.iemobile) { - const ie = "msie"; + + + + // IE11 has a new token so we will assign it msie to avoid breaking changes + + if ( browser.rv || browser.iemobile) { + + var ie = "msie"; + + + matched.browser = ie; + browser[ie] = true; + } - if (browser.edge) { + + + + // Legacy Edge is officially known as Microsoft Edge, so rewrite the key to match + + if ( browser.edge ) { + delete browser.edge; - const msedge_legacy = "msedge"; - matched.browser = msedge_legacy; - browser[msedge_legacy] = true; - } - if (browser.opr && matched.browser === "opr") { - matched.browser = "opera"; - browser.opera = true; - } - if (matched.platform) { - const platformName = matched.platform.toLowerCase(); - if (platformName === "android" || platformName === "kindle" || platformName === "silk" || platformName === "blackberry" || platformName === "playbook") { - if (matched.browser === "safari" || matched.browser === "webkit" || (!matched.browser || matched.browser === "")) { - matched.browser = platformName; - browser[platformName] = true; - } - } - } - if (browser.bb && !browser.blackberry) { - browser.blackberry = true; - matched.browser = "blackberry"; + + var msedge = "msedge"; + + + + matched.browser = msedge; + + browser[msedge] = true; + + } + + + + // Blackberry browsers are marked as Safari on BlackBerry + + if ( browser.safari && browser.blackberry ) { + + var blackberry = "blackberry"; + + + + matched.browser = blackberry; + + browser[blackberry] = true; + + } + + + + // Playbook browsers are marked as Safari on Playbook + + if ( browser.safari && browser.playbook ) { + + var playbook = "playbook"; + + + + matched.browser = playbook; + + browser[playbook] = true; + } + + + + // BB10 is a newer OS version of BlackBerry + + if ( browser.bb ) { + + var bb = "blackberry"; + + + + matched.browser = bb; + + browser[bb] = true; + + } + + + + // Opera 15+ are identified as opr + + if ( browser.opr ) { + + var opera = "opera"; + + + + matched.browser = opera; + + browser[opera] = true; + + } + + + + // Stock Android browsers are marked as Safari on Android. + + if ( browser.safari && browser.android ) { + + var android = "android"; + + + + matched.browser = android; + + browser[android] = true; + + } + + + + // Kindle browsers are marked as Safari on Kindle + + if ( browser.safari && browser.kindle ) { + + var kindle = "kindle"; + + + + matched.browser = kindle; + + browser[kindle] = true; + + } + + + + // Kindle Silk browsers are marked as Safari on Kindle + + if ( browser.safari && browser.silk ) { + + var silk = "silk"; + + + + matched.browser = silk; + + browser[silk] = true; + + } + + + + // Assign the name and platform variable + browser.name = matched.browser; + browser.platform = matched.platform; - browser.uaMatch = uaMatch; + return browser; + } - function factory(jQuery) { - if (typeof window !== "undefined") { - window.jQBrowser = uaMatch(window.navigator.userAgent); - window.jQBrowser.uaMatch = uaMatch; - if (jQuery) { - jQuery.browser = window.jQBrowser; - } - return window.jQBrowser; - } else { - const browser = uaMatch(); - browser.uaMatch = uaMatch; - return browser; - } + + + + // Run the matching process, also assign the function to the returned object + + // for manual, jQuery-free use if desired + + window.jQBrowser = uaMatch( window.navigator.userAgent ); + + window.jQBrowser.uaMatch = uaMatch; + + + + // Only assign to jQuery.browser if jQuery is loaded + + if ( jQuery ) { + + jQuery.browser = window.jQBrowser; + } - (function(factoryFunc) { - const isESModule = typeof module !== "undefined" && module.exports && Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(module, "exports")?.writable === false; - if (!isESModule) { - if (typeof define === "function" && define.amd) { - define(["jquery"], function($) { - return factoryFunc($); - }); - } else if (typeof module === "object" && typeof module.exports === "object") { - try { - module.exports = factoryFunc(__require("jquery")); - } catch (e) { - factoryFunc(typeof window !== "undefined" ? window.jQuery : void 0); - } - } else { - factoryFunc(typeof window !== "undefined" ? window.jQuery : void 0); - } - } - })(factory); - var jquery_browser_default = factory; - return __toCommonJS(jquery_browser_exports); -})(); + + + + return window.jQBrowser; + +})); + diff --git a/dist/jquery.browser.min.js b/dist/jquery.browser.min.js index 3cf1c2b..9f2c481 100644 --- a/dist/jquery.browser.min.js +++ b/dist/jquery.browser.min.js @@ -1,2 +1,13 @@ /*!\n * jQuery Browser Plugin \n * https://github.com/melloware/jquery-browser-plugin\n *\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\n * http://jquery.org/license\n *\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\n * https://github.com/melloware\n *\n * Released under the MIT license\n */ -"use strict";/*!\n * jQuery Browser Plugin \n * https://github.com/melloware/jquery-browser-plugin\n *\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\n * http://jquery.org/license\n *\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\n * https://github.com/melloware\n *\n * Released under the MIT license\n */var jQBrowser=(()=>{var d=Object.defineProperty,p=Object.getOwnPropertyDescriptor,b=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,l=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,n)=>(typeof require<"u"?require:o)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),m=(e,o)=>{for(var n in o)d(e,n,{get:o[n],enumerable:!0})},u=(e,o,n,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let w of b(o))!a.call(e,w)&&w!==n&&d(e,w,{get:()=>o[w],enumerable:!(r=p(o,w))||r.enumerable});return e},y=e=>u(d({},"__esModule",{value:!0}),e),f={};m(f,{default:()=>x,factory:()=>c,uaMatch:()=>s});function s(e){e===void 0&&(typeof window<"u"&&window.navigator?e=window.navigator.userAgent:e=""),e=e.toLowerCase();const o=/(edg|edga|edgios)\/([\w.]+)/.exec(e)||/(edge)\/([\w.]+)/.exec(e)||/(opr)[\/]([\w.]+)/.exec(e)||/(chrome)[ \/]([\w.]+)/.exec(e)||/(iemobile)[\/]([\w.]+)/.exec(e)||/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("trident")>=0&&/(rv)(?::| )([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[],n=/(ipad)/.exec(e)||/(ipod)/.exec(e)||/(windows phone)/.exec(e)||/(iphone)/.exec(e)||/(kindle)/.exec(e)||/(silk)/.exec(e)||/(android)/.exec(e)||/(win)/.exec(e)||/(mac)/.exec(e)||/(linux)/.exec(e)||/(cros)/.exec(e)||/(playbook)/.exec(e)||/(bb)/.exec(e)||/(blackberry)/.exec(e)||[],r={},i={browser:o[1]==="edg"||o[1]==="edga"||o[1]==="edgios"?"msedge":o[5]||o[3]||o[1]||"",version:o[2]||o[4]||"0",versionNumber:o[4]||o[2]||"0",platform:n[0]||""};if(i.browser&&(r[i.browser]=!0,r.version=i.version,r.versionNumber=parseInt(i.versionNumber,10)),i.platform&&(r[i.platform]=!0),(r.android||r.bb||r.blackberry||r.ipad||r.iphone||r.ipod||r.kindle||r.playbook||r.silk||r["windows phone"])&&(r.mobile=!0),(r.cros||r.mac||r.linux||r.win)&&(r.desktop=!0),(r.chrome||r.opr||r.safari||r.msedge)&&(r.webkit=!0),r.rv||r.iemobile){const t="msie";i.browser=t,r[t]=!0}if(r.edge){delete r.edge;const t="msedge";i.browser=t,r[t]=!0}if(r.opr&&i.browser==="opr"&&(i.browser="opera",r.opera=!0),i.platform){const t=i.platform.toLowerCase();(t==="android"||t==="kindle"||t==="silk"||t==="blackberry"||t==="playbook")&&(i.browser==="safari"||i.browser==="webkit"||!i.browser||i.browser==="")&&(i.browser=t,r[t]=!0)}return r.bb&&!r.blackberry&&(r.blackberry=!0,i.browser="blackberry"),r.name=i.browser,r.platform=i.platform,r.uaMatch=s,r}function c(e){if(typeof window<"u")return window.jQBrowser=s(window.navigator.userAgent),window.jQBrowser.uaMatch=s,e&&(e.browser=window.jQBrowser),window.jQBrowser;{const o=s();return o.uaMatch=s,o}}(function(e){if(!(typeof module<"u"&&module.exports&&Object.getOwnPropertyDescriptor&&Object.getOwnPropertyDescriptor(module,"exports")?.writable===!1))if(typeof define=="function"&&define.amd)define(["jquery"],function(n){return e(n)});else if(typeof module=="object"&&typeof module.exports=="object")try{module.exports=e(l("jquery"))}catch{e(typeof window<"u"?window.jQuery:void 0)}else e(typeof window<"u"?window.jQuery:void 0)})(c);var x=c;return y(f)})(); +"use strict";/*! + * jQuery Browser Plugin + * https://github.com/melloware/jquery-browser-plugin + * + * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors + * http://jquery.org/license + * + * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware + * https://github.com/melloware + * + * Released under the MIT license + */(function(s){typeof define=="function"&&define.amd?define(["jquery"],function(w){return s(w)}):typeof module=="object"&&typeof module.exports=="object"?module.exports=s(require("jquery")):s(window.jQuery)})(function(s){"use strict";function w(r){r===void 0&&(r=window.navigator.userAgent),r=r.toLowerCase();var o=/(edg|edga|edgios)\/([\w.]+)/.exec(r)||/(edge)\/([\w.]+)/.exec(r)||/(opr)[\/]([\w.]+)/.exec(r)||/(chrome)[ \/]([\w.]+)/.exec(r)||/(iemobile)[\/]([\w.]+)/.exec(r)||/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(r)||/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(r)||/(webkit)[ \/]([\w.]+)/.exec(r)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(r)||/(msie) ([\w.]+)/.exec(r)||r.indexOf("trident")>=0&&/(rv)(?::| )([\w.]+)/.exec(r)||r.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(r)||[],p=/(ipad)/.exec(r)||/(ipod)/.exec(r)||/(windows phone)/.exec(r)||/(iphone)/.exec(r)||/(kindle)/.exec(r)||/(silk)/.exec(r)||/(android)/.exec(r)||/(win)/.exec(r)||/(mac)/.exec(r)||/(linux)/.exec(r)||/(cros)/.exec(r)||/(playbook)/.exec(r)||/(bb)/.exec(r)||/(blackberry)/.exec(r)||[],e={},i={browser:o[5]||o[3]||o[1]||"",version:o[2]||o[4]||"0",versionNumber:o[4]||o[2]||"0",platform:p[0]||""},n=i.browser==="edg"||i.browser==="edga"||i.browser==="edgios";if(n&&(i.browser="msedge"),i.browser&&(e[i.browser]=!0,e.version=i.version,e.versionNumber=parseInt(i.versionNumber,10)),i.platform&&(e[i.platform]=!0),(e.android||e.bb||e.blackberry||e.ipad||e.iphone||e.ipod||e.kindle||e.playbook||e.silk||e["windows phone"])&&(e.mobile=!0),(e.cros||e.mac||e.linux||e.win)&&(e.desktop=!0),(e.chrome||e.opr||e.safari||e.msedge&&n)&&(e.webkit=!0),e.rv||e.iemobile){var t="msie";i.browser=t,e[t]=!0}if(e.edge){delete e.edge;var d="msedge";i.browser=d,e[d]=!0}if(e.safari&&e.blackberry){var c="blackberry";i.browser=c,e[c]=!0}if(e.safari&&e.playbook){var b="playbook";i.browser=b,e[b]=!0}if(e.bb){var f="blackberry";i.browser=f,e[f]=!0}if(e.opr){var a="opera";i.browser=a,e[a]=!0}if(e.safari&&e.android){var l="android";i.browser=l,e[l]=!0}if(e.safari&&e.kindle){var m="kindle";i.browser=m,e[m]=!0}if(e.safari&&e.silk){var x="silk";i.browser=x,e[x]=!0}return e.name=i.browser,e.platform=i.platform,e}return window.jQBrowser=w(window.navigator.userAgent),window.jQBrowser.uaMatch=w,s&&(s.browser=window.jQBrowser),window.jQBrowser}); diff --git a/package-lock.json b/package-lock.json index a98a026..f5c1f9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@melloware/jquery.browser", - "version": "0.9.0-beta.1", + "version": "0.9.0-beta.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@melloware/jquery.browser", - "version": "0.9.0-beta.1", + "version": "0.9.0-beta.2", "license": "MIT", "devDependencies": { "@types/jquery": "^3.5.33", diff --git a/package.json b/package.json index 24c5a6a..1762b69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@melloware/jquery.browser", - "version": "0.9.0-beta.1", + "version": "0.9.0-beta.2", "description": "A jQuery plugin for browser detection.", "license": "MIT", "author": "jQuery Team ", @@ -30,10 +30,10 @@ ], "scripts": { "build": "npm run build:types && npm run build:umd && npm run build:minify", - "build:types": "tsc --emitDeclarationOnly --declarationMap", - "build:umd": "esbuild src/jquery.browser.ts --bundle --format=iife --global-name=jQBrowser --outfile=dist/jquery.browser.js --banner:js=\"/*!\\n * jQuery Browser Plugin \\n * https://github.com/melloware/jquery-browser-plugin\\n *\\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\\n * http://jquery.org/license\\n *\\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\\n * https://github.com/melloware\\n *\\n * Released under the MIT license\\n */\" --external:jquery", + "build:types": "node -e \"require('fs').copyFileSync('src/jquery.browser.d.ts', 'dist/jquery.browser.d.ts')\"", + "build:umd": "node -e \"const fs=require('fs');const banner='/*!\\n * jQuery Browser Plugin \\n * https://github.com/melloware/jquery-browser-plugin\\n *\\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\\n * http://jquery.org/license\\n *\\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\\n * https://github.com/melloware\\n *\\n * Released under the MIT license\\n */\\n';fs.writeFileSync('dist/jquery.browser.js', banner + fs.readFileSync('src/jquery.browser.js', 'utf-8'))\"", "build:minify": "esbuild dist/jquery.browser.js --minify --outfile=dist/jquery.browser.min.js --banner:js=\"/*!\\n * jQuery Browser Plugin \\n * https://github.com/melloware/jquery-browser-plugin\\n *\\n * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors\\n * http://jquery.org/license\\n *\\n * Modifications Copyright 2015 Gabriel Cebrian, 2025 Melloware\\n * https://github.com/melloware\\n *\\n * Released under the MIT license\\n */\"", - "type-check": "tsc --noEmit", + "type-check": "tsc --noEmit --project tsconfig.json", "test": "vitest run", "test:watch": "vitest", "test:ui": "vitest --ui" diff --git a/src/jquery.browser.d.ts b/src/jquery.browser.d.ts new file mode 100644 index 0000000..fa4b5a6 --- /dev/null +++ b/src/jquery.browser.d.ts @@ -0,0 +1,66 @@ +/** + * Browser detection result interface + */ +export interface BrowserDetection { + // Browser flags + msie?: boolean; + webkit?: boolean; + mozilla?: boolean; + chrome?: boolean; + safari?: boolean; + opr?: boolean; + opera?: boolean; + msedge?: boolean; + edge?: boolean; + rv?: boolean; + iemobile?: boolean; + + // Platform flags + android?: boolean; + blackberry?: boolean; + cros?: boolean; + ipad?: boolean; + iphone?: boolean; + ipod?: boolean; + kindle?: boolean; + linux?: boolean; + mac?: boolean; + playbook?: boolean; + silk?: boolean; + win?: boolean; + "windows phone"?: boolean; + bb?: boolean; + + // Classification flags + mobile?: boolean; + desktop?: boolean; + + // Metadata + name: string; + version: string; + versionNumber: number; + platform: string; + + // Function to match arbitrary user agents + uaMatch: (ua?: string) => BrowserDetection; +} + +/** + * jQuery interface extension + */ +interface JQueryStatic { + browser: BrowserDetection; +} + +/** + * Global window interface extension + */ +declare global { + interface Window { + jQBrowser: BrowserDetection; + jQuery?: JQueryStatic; + } +} + +export {}; + diff --git a/src/jquery.browser.js b/src/jquery.browser.js new file mode 100644 index 0000000..579dd47 --- /dev/null +++ b/src/jquery.browser.js @@ -0,0 +1,179 @@ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], function ($) { + return factory($); + }); + } else if (typeof module === 'object' && typeof module.exports === 'object') { + // Node-like environment + module.exports = factory(require('jquery')); + } else { + // Browser globals + factory(window.jQuery); + } +}(function (jQuery) { + "use strict"; + + function uaMatch(ua) { + // If an UA is not provided, default to the current browser UA. + if (ua === undefined) { + ua = window.navigator.userAgent; + } + + ua = ua.toLowerCase(); + + var match = /(edg|edga|edgios)\/([\w.]+)/.exec(ua) || + /(edge)\/([\w.]+)/.exec(ua) || + /(opr)[\/]([\w.]+)/.exec(ua) || + /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(iemobile)[\/]([\w.]+)/.exec(ua) || + /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + var platform_match = /(ipad)/.exec(ua) || + /(ipod)/.exec(ua) || + /(windows phone)/.exec(ua) || + /(iphone)/.exec(ua) || + /(kindle)/.exec(ua) || + /(silk)/.exec(ua) || + /(android)/.exec(ua) || + /(win)/.exec(ua) || + /(mac)/.exec(ua) || + /(linux)/.exec(ua) || + /(cros)/.exec(ua) || + /(playbook)/.exec(ua) || + /(bb)/.exec(ua) || + /(blackberry)/.exec(ua) || + []; + + var browser = {}, + matched = { + browser: match[5] || match[3] || match[1] || "", + version: match[2] || match[4] || "0", + versionNumber: match[4] || match[2] || "0", + platform: platform_match[0] || "" + }; + + // Track if this is Chromium Edge (before normalization) + var isChromiumEdge = matched.browser === "edg" || matched.browser === "edga" || matched.browser === "edgios"; + + // Normalize Chromium Edge (edg/edga/edgios) to msedge + if (isChromiumEdge) { + matched.browser = "msedge"; + } + + if (matched.browser) { + browser[matched.browser] = true; + browser.version = matched.version; + browser.versionNumber = parseInt(matched.versionNumber, 10); + } + + if (matched.platform) { + browser[matched.platform] = true; + } + + // These are all considered mobile platforms, meaning they run a mobile browser + if (browser.android || browser.bb || browser.blackberry || browser.ipad || browser.iphone || + browser.ipod || browser.kindle || browser.playbook || browser.silk || browser["windows phone"]) { + browser.mobile = true; + } + + // These are all considered desktop platforms, meaning they run a desktop browser + if (browser.cros || browser.mac || browser.linux || browser.win) { + browser.desktop = true; + } + + // Chrome, Opera 15+, Safari, and Chromium Edge are webkit based browsers + // Note: Only Chromium Edge (not legacy Edge) is webkit-based + if (browser.chrome || browser.opr || browser.safari || (browser.msedge && isChromiumEdge)) { + browser.webkit = true; + } + + // IE11 has a new token so we will assign it msie to avoid breaking changes + if (browser.rv || browser.iemobile) { + var ie = "msie"; + matched.browser = ie; + browser[ie] = true; + } + + // Legacy Edge is officially known as Microsoft Edge, so rewrite the key to match + if (browser.edge) { + delete browser.edge; + var msedge = "msedge"; + matched.browser = msedge; + browser[msedge] = true; + } + + // Blackberry browsers are marked as Safari on BlackBerry + if (browser.safari && browser.blackberry) { + var blackberry = "blackberry"; + matched.browser = blackberry; + browser[blackberry] = true; + } + + // Playbook browsers are marked as Safari on Playbook + if (browser.safari && browser.playbook) { + var playbook = "playbook"; + matched.browser = playbook; + browser[playbook] = true; + } + + // BB10 is a newer OS version of BlackBerry + if (browser.bb) { + var bb = "blackberry"; + matched.browser = bb; + browser[bb] = true; + } + + // Opera 15+ are identified as opr + if (browser.opr) { + var opera = "opera"; + matched.browser = opera; + browser[opera] = true; + } + + // Stock Android browsers are marked as Safari on Android. + if (browser.safari && browser.android) { + var android = "android"; + matched.browser = android; + browser[android] = true; + } + + // Kindle browsers are marked as Safari on Kindle + if (browser.safari && browser.kindle) { + var kindle = "kindle"; + matched.browser = kindle; + browser[kindle] = true; + } + + // Kindle Silk browsers are marked as Safari on Kindle + if (browser.safari && browser.silk) { + var silk = "silk"; + matched.browser = silk; + browser[silk] = true; + } + + // Assign the name and platform variable + browser.name = matched.browser; + browser.platform = matched.platform; + return browser; + } + + // Run the matching process, also assign the function to the returned object + // for manual, jQuery-free use if desired + window.jQBrowser = uaMatch(window.navigator.userAgent); + window.jQBrowser.uaMatch = uaMatch; + + // Only assign to jQuery.browser if jQuery is loaded + if (jQuery) { + jQuery.browser = window.jQBrowser; + } + + return window.jQBrowser; +})); diff --git a/src/jquery.browser.ts b/src/jquery.browser.ts deleted file mode 100644 index 6099fea..0000000 --- a/src/jquery.browser.ts +++ /dev/null @@ -1,310 +0,0 @@ -/** - * Browser detection result interface - */ -export interface BrowserDetection { - // Browser flags - msie?: boolean; - webkit?: boolean; - mozilla?: boolean; - chrome?: boolean; - safari?: boolean; - opr?: boolean; - opera?: boolean; - msedge?: boolean; - edge?: boolean; - rv?: boolean; - iemobile?: boolean; - - // Platform flags - android?: boolean; - blackberry?: boolean; - cros?: boolean; - ipad?: boolean; - iphone?: boolean; - ipod?: boolean; - kindle?: boolean; - linux?: boolean; - mac?: boolean; - playbook?: boolean; - silk?: boolean; - win?: boolean; - "windows phone"?: boolean; - bb?: boolean; - - // Classification flags - mobile?: boolean; - desktop?: boolean; - - // Metadata - name: string; - version: string; - versionNumber: number; - platform: string; - - // Function to match arbitrary user agents - uaMatch: (ua?: string) => BrowserDetection; -} - -/** - * jQuery interface extension - */ -interface JQueryStatic { - browser: BrowserDetection; -} - -/** - * Global window interface extension - */ -declare global { - interface Window { - jQBrowser: BrowserDetection; - jQuery?: JQueryStatic; - } -} - -/** - * Matches a user agent string and returns browser detection information - * @param ua - Optional user agent string. If not provided, uses navigator.userAgent - * @returns Browser detection object - */ -function uaMatch(ua?: string): BrowserDetection { - // If an UA is not provided, default to the current browser UA. - if (ua === undefined) { - if (typeof window !== 'undefined' && window.navigator) { - ua = window.navigator.userAgent; - } else { - ua = ''; - } - } - ua = ua.toLowerCase(); - - const match = - // Chromium Edge (Edg/EdgA/EdgIOS) - must come before Chrome to avoid false positives - /(edg|edga|edgios)\/([\w.]+)/.exec(ua) || - // Legacy Edge (EdgeHTML) - must come before Chrome - /(edge)\/([\w.]+)/.exec(ua) || - // Opera 15+ (OPR) - must come before Chrome - /(opr)[\/]([\w.]+)/.exec(ua) || - // Chrome - must come before Safari - /(chrome)[ \/]([\w.]+)/.exec(ua) || - // IE Mobile - /(iemobile)[\/]([\w.]+)/.exec(ua) || - // Safari (with version) - specific pattern for Safari - /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || - // Safari (alternative pattern) - /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || - // WebKit (generic) - catch-all for WebKit browsers - /(webkit)[ \/]([\w.]+)/.exec(ua) || - // Opera (legacy Presto engine) - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - // IE (legacy MSIE token) - /(msie) ([\w.]+)/.exec(ua) || - // IE 11 (Trident engine with rv: token) - (ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua)) || - // Firefox (Gecko engine, not compatible mode) - (ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)) || - []; - - const platform_match = - /(ipad)/.exec(ua) || - /(ipod)/.exec(ua) || - /(windows phone)/.exec(ua) || - /(iphone)/.exec(ua) || - /(kindle)/.exec(ua) || - /(silk)/.exec(ua) || - /(android)/.exec(ua) || - /(win)/.exec(ua) || - /(mac)/.exec(ua) || - /(linux)/.exec(ua) || - /(cros)/.exec(ua) || - /(playbook)/.exec(ua) || - /(bb)/.exec(ua) || - /(blackberry)/.exec(ua) || - []; - - const browser: BrowserDetection = {} as BrowserDetection; - - // Normalize new Chromium Edge naming - const browserName = - match[1] === "edg" || - match[1] === "edga" || - match[1] === "edgios" - ? "msedge" - : match[5] || match[3] || match[1] || ""; - - const matched = { - browser: browserName, - version: match[2] || match[4] || "0", - versionNumber: match[4] || match[2] || "0", - platform: platform_match[0] || "" - }; - - if (matched.browser) { - (browser as any)[matched.browser] = true; - browser.version = matched.version; - browser.versionNumber = parseInt(matched.versionNumber, 10); - } - - if (matched.platform) { - (browser as any)[matched.platform] = true; - } - - // These are all considered mobile platforms, meaning they run a mobile browser - if ( - browser.android || - browser.bb || - browser.blackberry || - browser.ipad || - browser.iphone || - browser.ipod || - browser.kindle || - browser.playbook || - browser.silk || - browser["windows phone"] - ) { - browser.mobile = true; - } - - // These are all considered desktop platforms - if (browser.cros || browser.mac || browser.linux || browser.win) { - browser.desktop = true; - } - - // Chrome, Opera 15+ and Safari are webkit based browsers - // Note: Modern Edge (Chromium) is also webkit-based - if (browser.chrome || browser.opr || browser.safari || browser.msedge) { - browser.webkit = true; - } - - // IE11 has a new token so we will assign it msie to avoid breaking changes - if (browser.rv || browser.iemobile) { - const ie = "msie"; - matched.browser = ie; - (browser as any)[ie] = true; - } - - // Legacy Edge is officially known as Microsoft Edge, so rewrite the key - if (browser.edge) { - delete browser.edge; - const msedge_legacy = "msedge"; - matched.browser = msedge_legacy; - (browser as any)[msedge_legacy] = true; - } - - // Opera 15+ (OPR) should normalize to "opera" for consistency - if (browser.opr && matched.browser === "opr") { - matched.browser = "opera"; - browser.opera = true; - } - - // Platform-based browsers: if platform is detected and it's a browser platform, - // use it as the browser name (Android, Kindle, Silk, BlackBerry, PlayBook) - if (matched.platform) { - const platformName = matched.platform.toLowerCase(); - if ( - platformName === "android" || - platformName === "kindle" || - platformName === "silk" || - platformName === "blackberry" || - platformName === "playbook" - ) { - // Only override if we haven't already set a specific browser name - // (e.g., don't override Chrome on Android) - if ( - matched.browser === "safari" || - matched.browser === "webkit" || - (!matched.browser || matched.browser === "") - ) { - matched.browser = platformName; - (browser as any)[platformName] = true; - } - } - } - - // BB10 platform should normalize to blackberry browser name - if (browser.bb && !browser.blackberry) { - browser.blackberry = true; - matched.browser = "blackberry"; - } - - // Assign name & platform - browser.name = matched.browser; - browser.platform = matched.platform; - - // Add uaMatch function to the browser object - browser.uaMatch = uaMatch; - - return browser; -} - -/** - * Factory function for module systems (AMD, CommonJS, Browser globals) - */ -function factory(jQuery?: JQueryStatic): BrowserDetection { - // Run the matching process, also assign the function to the returned object - // for manual, jQuery-free use if desired - if (typeof window !== 'undefined') { - window.jQBrowser = uaMatch(window.navigator.userAgent); - window.jQBrowser.uaMatch = uaMatch; - - // Only assign to jQuery.browser if jQuery is loaded - if (jQuery) { - jQuery.browser = window.jQBrowser; - } - - return window.jQBrowser; - } else { - // Node.js environment - const browser = uaMatch(); - browser.uaMatch = uaMatch; - return browser; - } -} - -// Declare AMD and CommonJS globals for TypeScript -declare const define: { - (deps: string[], factory: (...args: any[]) => any): void; - amd?: boolean; -} | undefined; - -declare const module: { - exports: any; -} | undefined; - -declare function require(id: string): any; - -// UMD wrapper - matches original pattern exactly -// Only execute in non-ES module environments (browser, AMD, CommonJS) -// In ES module environments, exports are handled by the export statements below -(function (factoryFunc: (jQuery?: JQueryStatic) => BrowserDetection) { - // Check if we're in an ES module environment - // In ES modules, module.exports might be read-only, so we check for that - const isESModule = typeof module !== 'undefined' && module.exports && - Object.getOwnPropertyDescriptor && - Object.getOwnPropertyDescriptor(module, 'exports')?.writable === false; - - if (!isESModule) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['jquery'], function ($: JQueryStatic) { - return factoryFunc($); - }); - } else if (typeof module === 'object' && typeof module.exports === 'object') { - // CommonJS environment - try { - module.exports = factoryFunc(require('jquery')); - } catch (e) { - // If require fails or module.exports is read-only, just execute factory for browser - factoryFunc(typeof window !== 'undefined' ? (window as any).jQuery : undefined); - } - } else { - // Browser globals - factoryFunc(typeof window !== 'undefined' ? (window as any).jQuery : undefined); - } - } -}(factory)); - -// Export for ES modules and TypeScript (for development/testing) -export { uaMatch, factory }; -export default factory; - diff --git a/test/helpers.ts b/test/helpers.ts new file mode 100644 index 0000000..4576234 --- /dev/null +++ b/test/helpers.ts @@ -0,0 +1,175 @@ +/** + * Test helper to expose uaMatch function + * This is a direct implementation from src/jquery.browser.js adapted for testing + */ +import type { BrowserDetection } from '../src/jquery.browser.d.ts'; + +export function uaMatch(ua?: string): BrowserDetection { + // If an UA is not provided, default to the current browser UA. + if (ua === undefined) { + if (typeof window !== 'undefined' && window.navigator) { + ua = window.navigator.userAgent; + } else { + ua = ''; + } + } + ua = ua.toLowerCase(); + + const match = + /(edg|edga|edgios)\/([\w.]+)/.exec(ua) || + /(edge)\/([\w.]+)/.exec(ua) || + /(opr)[\/]([\w.]+)/.exec(ua) || + /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(iemobile)[\/]([\w.]+)/.exec(ua) || + /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + (ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua)) || + (ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)) || + []; + + const platform_match = + /(ipad)/.exec(ua) || + /(ipod)/.exec(ua) || + /(windows phone)/.exec(ua) || + /(iphone)/.exec(ua) || + /(kindle)/.exec(ua) || + /(silk)/.exec(ua) || + /(android)/.exec(ua) || + /(win)/.exec(ua) || + /(mac)/.exec(ua) || + /(linux)/.exec(ua) || + /(cros)/.exec(ua) || + /(playbook)/.exec(ua) || + /(bb)/.exec(ua) || + /(blackberry)/.exec(ua) || + []; + + const browser: any = {}; + const matched = { + browser: match[5] || match[3] || match[1] || "", + version: match[2] || match[4] || "0", + versionNumber: match[4] || match[2] || "0", + platform: platform_match[0] || "" + }; + + // Track if this is Chromium Edge (before normalization) + const isChromiumEdge = matched.browser === "edg" || matched.browser === "edga" || matched.browser === "edgios"; + + // Normalize Chromium Edge (edg/edga/edgios) to msedge + if (isChromiumEdge) { + matched.browser = "msedge"; + } + + if (matched.browser) { + browser[matched.browser] = true; + browser.version = matched.version; + browser.versionNumber = parseInt(matched.versionNumber, 10); + } + + if (matched.platform) { + browser[matched.platform] = true; + } + + // These are all considered mobile platforms, meaning they run a mobile browser + if ( + browser.android || + browser.bb || + browser.blackberry || + browser.ipad || + browser.iphone || + browser.ipod || + browser.kindle || + browser.playbook || + browser.silk || + browser["windows phone"] + ) { + browser.mobile = true; + } + + // These are all considered desktop platforms, meaning they run a desktop browser + if (browser.cros || browser.mac || browser.linux || browser.win) { + browser.desktop = true; + } + + // Chrome, Opera 15+, Safari, and Chromium Edge are webkit based browsers + // Note: Only Chromium Edge (not legacy Edge) is webkit-based + if (browser.chrome || browser.opr || browser.safari || (browser.msedge && isChromiumEdge)) { + browser.webkit = true; + } + + // IE11 has a new token so we will assign it msie to avoid breaking changes + if (browser.rv || browser.iemobile) { + const ie = "msie"; + matched.browser = ie; + browser[ie] = true; + } + + // Legacy Edge is officially known as Microsoft Edge, so rewrite the key to match + if (browser.edge) { + delete browser.edge; + const msedge = "msedge"; + matched.browser = msedge; + browser[msedge] = true; + } + + // Blackberry browsers are marked as Safari on BlackBerry + if (browser.safari && browser.blackberry) { + const blackberry = "blackberry"; + matched.browser = blackberry; + browser[blackberry] = true; + } + + // Playbook browsers are marked as Safari on Playbook + if (browser.safari && browser.playbook) { + const playbook = "playbook"; + matched.browser = playbook; + browser[playbook] = true; + } + + // BB10 is a newer OS version of BlackBerry + if (browser.bb) { + const bb = "blackberry"; + matched.browser = bb; + browser[bb] = true; + } + + // Opera 15+ are identified as opr + if (browser.opr) { + const opera = "opera"; + matched.browser = opera; + browser[opera] = true; + } + + // Stock Android browsers are marked as Safari on Android. + if (browser.safari && browser.android) { + const android = "android"; + matched.browser = android; + browser[android] = true; + } + + // Kindle browsers are marked as Safari on Kindle + if (browser.safari && browser.kindle) { + const kindle = "kindle"; + matched.browser = kindle; + browser[kindle] = true; + } + + // Kindle Silk browsers are marked as Safari on Kindle + if (browser.safari && browser.silk) { + const silk = "silk"; + matched.browser = silk; + browser[silk] = true; + } + + // Assign the name and platform variable + browser.name = matched.browser; + browser.platform = matched.platform; + browser.uaMatch = uaMatch; + + return browser as BrowserDetection; +} + +export type { BrowserDetection } from '../src/jquery.browser.d.ts'; diff --git a/test/jquery.browser.test.ts b/test/jquery.browser.test.ts index afcc148..e3d3575 100644 --- a/test/jquery.browser.test.ts +++ b/test/jquery.browser.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { uaMatch } from '../src/jquery.browser'; -import type { BrowserDetection } from '../src/jquery.browser'; +import { uaMatch } from './helpers'; +import type { BrowserDetection } from './helpers'; // User agent test data const ua = { diff --git a/tsconfig.json b/tsconfig.json index bf0fc3a..c093b47 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,9 +13,10 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "noEmitOnError": true, - "removeComments": false + "removeComments": false, + "emitDeclarationOnly": true }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "test"] + "include": ["src/jquery.browser.d.ts"], + "exclude": ["node_modules", "dist", "test", "src/**/*.js"] }