text: var UNKNOWN_VERSION = null;
  var d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests = {
  
      'GWT': {
          id: 'gwt',
          icon: 'gwt',
          url: 'http://www.gwtproject.org/',
          test: function(win) {
              // pretty complicated, many possible tell tales
              var doc = win.document,
                  hasHistFrame = doc.getElementById('__gwt_historyFrame'),
                  hasGwtUid = doc.gwt_uid,
                  hasBodyListener = doc.body.__listener,
                  hasBodyEventBits = doc.body.__eventBits,
                  hasModules = win.__gwt_activeModules,
                  hasJsonP = win.__gwt_jsonp__,
                  hasRootWinApp = win.__gwt_scriptsLoaded || win.__gwt_stylesLoaded || win.__gwt_activeModules;
  
              // use the many possible indicators
              if(hasHistFrame || hasGwtUid || hasBodyListener || hasBodyEventBits || hasModules || hasJsonP || hasRootWinApp) {
  
                  // carefully look at frames, but only if certain is GWT frame
                  var frames = doc.getElementsByTagName('iframe'),
                      gwtVersion = UNKNOWN_VERSION;
                  for(var n=0; n<frames.length; n++) {
                      // catch security access errors
                      try {
                          var hasNegativeTabIndex = frames[n].tabIndex < 0; // on for GWT
                          if(hasNegativeTabIndex && frames[n].contentWindow && frames[n].contentWindow.$gwt_version) {
                              gwtVersion = frames[n].contentWindow.$gwt_version;
                              break;
                          }
                      }
                      catch(e) {}
                  }
  
                  if(gwtVersion=='0.0.999') {
                    gwtVersion = 'Google Internal';
                  }
  
                  return { version: gwtVersion };
              }
              return false;
          }
      },
  
      'Ink': {
          id: 'ink',
          icon: 'ink',
          url: 'http://ink.sapo.pt/',
          test: function(win) {
              if (win.Ink && win.Ink.createModule) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Vaadin': {
          id: 'vaadin',
          icon: 'vaadin',
          url: 'https://vaadin.com/',
          test: function(win) {
              if (win.vaadin && win.vaadin.registerWidgetset) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Bootstrap': {
          id: 'bootstrap',
          icon: 'bootstrap',
          url: 'http://getbootstrap.com/',
          npm: 'bootstrap',
          // look for a function Boostrap has added to jQuery - regex for BS 2 & 3
          test: function(win) {
              var jQueryAvailable = win.$ && win.$.fn,
                  RE_PREFIX_V2 = '\\$this\\.data\\((?:\'|")',
                  RE_PREFIX_V3 = '\\$this\\.data\\((?:\'|")(?:bs\\.){1}',
                  bootstrapComponents = [
                      'affix', 'alert', 'button', 'carousel', 'collapse', 'dropdown',
                      'modal', 'popover', 'scrollspy', 'tab', 'tooltip'
                  ];
  
              if(jQueryAvailable) {
                  var bootstrapVersion;
  
                  bootstrapComponents.some(function(component) {
                      if(win.$.fn[component]) {
                          // Bootstrap >= 3.2.0 detection
                          if(win.$.fn[component].Constructor && win.$.fn[component].Constructor.VERSION) {
                              bootstrapVersion = win.$.fn[component].Constructor.VERSION;
                              return true;
                          // Bootstrap >= 2.0.0 and <= 3.1.0 detection
                          } else if(new RegExp(RE_PREFIX_V3 + component).test(win.$.fn[component].toString())) {
                              bootstrapVersion = '>= 3.0.0 & <= 3.1.1';
                              return true;
                          // Bootstrap < 3.1.0 detection
                          } else if(new RegExp(RE_PREFIX_V2 + component).test(win.$.fn[component].toString())) {
                              bootstrapVersion = '>= 2.0.0 & <= 2.3.2';
                              return true;
                          }
                      }
  
                      return false;
                  });
  
                  if (bootstrapVersion) {
                      return { version: bootstrapVersion };
                  }
              }
  
              return false;
          }
      },
  
      'Zurb': {
          id: 'zurb',
          icon: 'zurb',
          url: 'https://foundation.zurb.com/',
          npm: 'foundation-sites',
          test: function(win) {
              if(win.Foundation && win.Foundation.Toggler) {
                  return { version: win.Foundation.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Polymer': {
          id: 'polymer',
          icon: 'polymer',
          url: 'https://www.polymer-project.org/',
          npm: '@polymer/polymer',
          test: function(win) {
              if(win.Polymer && win.Polymer.dom) {
                  return { version: win.Polymer.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Highcharts': {
          id: 'highcharts',
          icon: 'highcharts',
          url: 'http://www.highcharts.com',
          npm: 'highcharts',
          test: function(win) {
              if(win.Highcharts && win.Highcharts.Point) {
                  return { version: win.Highcharts.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'InfoVis': {
          id: 'jit',
          icon: 'jit',
          url: 'http://philogb.github.com/jit/',
          test: function test(win) {
              if(win.$jit && win.$jit.PieChart) {
                  return { version: win.$jit.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'FlotCharts': {
          id: 'flotcharts',
          icon: 'flotcharts',
          url: 'http://www.flotcharts.org/',
          npm: 'flot',
          test: function(win) {
              if(win.$ && win.$.plot) {
                  return { version: win.$.plot.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'CreateJS': {
          id: 'createjs',
          icon: 'createjs',
          url: 'https://createjs.com/',
          npm: 'createjs',
          test: function(win) {
              if(win.createjs && win.createjs.promote) {
                  return { version: UNKNOWN_VERSION}; // no version info available
              }
              return false;
          }
      },
  
      'Google Maps': {
          id: 'gmaps',
          icon: 'gmaps',
          url: 'https://developers.google.com/maps/',
          test: function(win) {
              if (win.google && win.google.maps) {
                  return { version: win.google.maps.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'jQuery': {
          id: 'jquery',
          icon: 'jquery',
          url: 'http://jquery.com',
          npm: 'jquery',
          test: function(win) {
              var jq = win.jQuery || win.$;
              if (jq && jq.fn && jq.fn.jquery) {
                  return { version: jq.fn.jquery.replace(/[^\d+\.+]/g, '') || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'jQuery (Fast path)': {
          id: 'jquery-fast',
          icon: 'jquery',
          url: 'http://jquery.com',
          npm: 'jquery',
          test: function (win) {
              var jq = win.jQuery || win.$;
              if (jq && jq.fn) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'jQuery UI': {
          id: 'jquery_ui',
          icon: 'jquery_ui',
          url: 'http://jqueryui.com',
          npm: 'jquery-ui',
          test: function(win) {
              var jq = win.jQuery || win.$ || win.$jq || win.$j;
              if(jq && jq.fn && jq.fn.jquery && jq.ui) {
                  var plugins = 'accordion,datepicker,dialog,draggable,droppable,progressbar,resizable,selectable,slider,menu,grid,tabs'.split(','), concat = [];
                  for (var i=0; i < plugins.length; i++) { if(jq.ui[plugins[i]]) concat.push(plugins[i].substr(0,1).toUpperCase() + plugins[i].substr(1)); }
                  return { version: jq.ui.version || UNKNOWN_VERSION, details: concat.length ? 'Plugins used: '+concat.join(',') : '' };
              }
              return false;
          }
      },
  
      'Dojo': {
          id: 'dojo',
          icon: 'dojo',
          url: 'http://dojotoolkit.org',
          npm: 'dojo',
          test: function(win) {
              if(win.dojo && win.dojo.delegate) {
                  var version = win.dojo.version ? win.dojo.version.toString() : UNKNOWN_VERSION;
                  return { version: version, details: 'Details: '+(win.dijit ? 'Uses Dijit' : 'none') };
              }
              return false;
          }
      },
  
      'Prototype': {
          id: 'prototype',
          icon: 'prototype',
          url: 'http://prototypejs.org',
          test: function(win) {
              if(win.Prototype && win.Prototype.BrowserFeatures) {
                  return { version: win.Prototype.Version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Scriptaculous': {
          id: 'scriptaculous',
          icon: 'scriptaculous',
          url: 'http://script.aculo.us',
          test: function(win) {
              if(win.Scriptaculous && win.Scriptaculous.load) {
                  return { version: win.Scriptaculous.Version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'MooTools': {
          id: 'mootools',
          icon: 'mootools',
          url: 'https://mootools.net/',
          test: function(win) {
              if(win.MooTools && win.MooTools.build) {
                  return { version: win.MooTools.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Spry': {
          id: 'spry',
          icon: 'spry',
          url: 'http://labs.adobe.com/technologies/spry',
          test: function(win) {
              if (win.Spry && win.Spry.Data) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'YUI 2': {
          id: 'yui',
          icon: 'yui',
          url: 'http://developer.yahoo.com/yui/2/',
          test: function(win) {
              if (win.YAHOO && win.YAHOO.util) {
                  return { version: win.YAHOO.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'YUI 3': {
          id: 'yui3',
          icon: 'yui3',
          url: 'https://yuilibrary.com/',
          npm: 'yui',
          test: function(win) {
              if (win.YUI && win.YUI.Env) {
                  return { version: win.YUI.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Qooxdoo': {
          id: 'qooxdoo',
          icon: 'qooxdoo',
          url: 'http://www.qooxdoo.org/',
          npm: 'qooxdoo',
          test: function(win) {
              if(win.qx && win.qx.Bootstrap) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Ext JS': {
          id: 'extjs',
          icon: 'extjs',
          url: 'https://www.sencha.com/products/extjs/',
          test: function(win) {
              if (win.Ext && win.Ext.versions) {
                  return { version: win.Ext.versions.core.version };
              }
              else if(win.Ext) {
                  return { version: win.Ext.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'base2': {
          id: 'base2',
          icon: 'base2',
          url: 'http://code.google.com/p/base2',
          test: function(win) {
              if(win.base2 && win.base2.dom) {
                  return { version: win.base2.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Closure Library': {
          id: 'closure',
          icon: 'closure',
          url: 'https://developers.google.com/closure/library/',
          npm: 'google-closure-library',
          test: function(win) {
              if(win.goog && win.goog.provide) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Rapha&euml;l': {
          id: 'raphael',
          icon: 'raphael',
          url: 'http://dmitrybaranovskiy.github.io/raphael/',
          test: function(win) {
              if (win.Raphael && win.Raphael.circle) {
                  return { version: win.Raphael.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'React': {
          id: 'react',
          icon: 'react',
          url: 'https://reactjs.org/',
          npm: 'react',
          test: function(win) {
              function isMatch(node) {
                  return node!=null && node._reactRootContainer!=null;
              }
              function nodeFilter(node) {
                  return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
              }
              var reactRoot = document.getElementById('react-root');
              var altHasReact = document.querySelector('*[data-reactroot]');
              var bodyReactRoot = isMatch(document.body) || isMatch(document.body.firstElementChild);
              var hasReactRoot = bodyReactRoot|| document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode() != null;
              if (hasReactRoot || reactRoot && reactRoot.innerText.length > 0 || altHasReact || win.React && win.React.Component) {
                  return { version: win.React && win.React.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'React (Fast path)': {
          id: 'react-fast',
          icon: 'react',
          url: 'https://reactjs.org/',
          npm: 'react',
          test: function (win) {
              function isMatch(node) {
                  return node != null && node._reactRootContainer != null;
              }
              var reactRoot = document.getElementById('react-root');
              var altHasReact = document.querySelector('*[data-reactroot]');
              var hasReactRoot = isMatch(document.body) || isMatch(document.body.firstElementChild);
              if (hasReactRoot || reactRoot || altHasReact || win.React) {
                  return { version: win.React && win.React.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Next.js': {
          id: 'next',
          icon: 'next',
          url: 'https://nextjs.org/',
          npm: 'next',
          test: function(win) {
              if (win.__NEXT_DATA__ && win.__NEXT_DATA__.buildId) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Next.js (Fast path)': {
          id: 'next-fast',
          icon: 'next',
          url: 'https://nextjs.org/',
          npm: 'next',
          test: function (win) {
              if (win.__NEXT_DATA__) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Preact': {
          id: 'preact',
          icon: 'preact',
          url: 'https://preactjs.com/',
          npm: 'preact',
          test: function(win) {
              var expando = typeof Symbol!='undefined' && Symbol.for && Symbol.for('preactattr');
              function isMatch(node) {
                  if ('__k' in node && 'props' in node.__k && 'type' in node.__k) {
                      return true;
                  }
                  return '_component' in node || '__preactattr_' in node || expando && node[expando]!=null;
              }
              function getMatch(node) {
                  return node!=null && isMatch(node) && node;
              }
              function nodeFilter(node) {
                  return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
              }
              var preactRoot = getMatch(document.body) || getMatch(document.body.firstElementChild);
              if (!preactRoot) {
                  preactRoot = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode();
              }
              if (preactRoot || win.preact) {
                  var version = UNKNOWN_VERSION;
                  if (expando && preactRoot && preactRoot[expando]!=null) {
                      version = '7';
                  }
                  if (preactRoot && '__k' in preactRoot) {
                      version = '10';
                  }
                  return { version: version };
              }
              return false;
          }
      },
  
      'Preact (Fast path)': {
          id: 'preact-fast',
          icon: 'preact',
          url: 'https://preactjs.com/',
          npm: 'preact',
          test: function (win) {
              function isMatch(node) {
                  return node._component != null || node.__preactattr_ != null;
              }
              function getMatch(node) {
                  return node != null && isMatch(node);
              }
              var preactRoot = getMatch(document.body) || getMatch(document.body.firstElementChild);
              if (preactRoot || win.preact) {
                  var version = UNKNOWN_VERSION;
                  return { version: version };
              }
              return false;
          }
      },
  
      'Modernizr': {
          id: 'modernizr',
          icon: 'modernizr',
          url: 'https://modernizr.com/',
          npm: 'modernizr',
          test: function(win) {
              if (win.Modernizr && win.Modernizr.addTest) {
                  return { version: win.Modernizr._version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Processing.js': {
          id: 'processingjs',
          icon: 'processingjs',
          url: 'http://processingjs.org',
          npm: 'processing-js',
          test: function(win) {
              if(win.Processing && win.Processing.box) {
                  return { version: Processing.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Backbone': {
          id: 'backbone',
          icon: 'backbone',
          url: 'http://backbonejs.org/',
          npm: 'backbone',
          test: function(win) {
              if (win.Backbone && win.Backbone.Model.extend) {
                  return {version: win.Backbone.VERSION || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Leaflet': {
          id: 'leaflet',
          icon: 'leaflet',
          url: 'http://leafletjs.com',
          npm: 'leaflet',
          test: function(win) {
              // Leaflet 3.1 uses L.Marker and L.VERSION; later versions use L.marker and L.version
              if (win.L && win.L.GeoJSON && (win.L.marker || win.L.Marker)) {
                  return { version: win.L.version || win.L.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Mapbox': {
          id: 'mapbox',
          icon: 'mapbox',
          url: 'https://www.mapbox.com/',
          npm: 'mapbox-gl',
          test: function(win) {
              if (win.L && win.L.mapbox && win.L.mapbox.geocoder) {
                  return { version: win.L.mapbox.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Lo-Dash': {
          id: 'lodash',
          icon: 'lodash',
          url: 'https://lodash.com/',
          npm: 'lodash',
          test: function(win) {
              var _ = typeof (_ = win._) == 'function' && _,
                  chain = typeof (chain = _ && _.chain) == 'function' && chain,
                  wrapper = (chain || _ || function() { return {}; })(1);
  
              if (_ && wrapper.__wrapped__) {
                  return { version: _.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Underscore': {
          id: 'underscore',
          icon: 'underscore',
          url: 'http://underscorejs.org/',
          npm: 'underscore',
          test: function(win) {
              if (win._ && typeof win._.tap === 'function' &&
                  !d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests['Lo-Dash'].test(win)) {
                  return {version: win._.VERSION || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Sammy': {
          id: 'sammy',
          icon: 'sammy',
          url: 'http://sammyjs.org',
          test: function(win) {
              if (win.Sammy && win.Sammy.Application.curry) {
                  return {version: win.Sammy.VERSION || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Rico': {
          id: 'rico',
          icon: 'rico',
          url: 'http://openrico.sourceforge.net/examples/index.html',
          test:  function(win) {
              if (win.Rico && window.Rico.checkIfComplete) {
                  return {version: win.Rico.Version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'MochiKit': {
          id: 'mochikit',
          icon: 'mochikit',
          url: 'https://mochi.github.io/mochikit/',
          test: function(win) {
              if (win.MochiKit && win.MochiKit.Base.module) {
                  return {version: MochiKit.VERSION || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'gRapha&euml;l': {
          id: 'graphael',
          icon: 'graphael',
          url: 'https://github.com/DmitryBaranovskiy/g.raphael',
          test: function(win) {
              if (win.Raphael && win.Raphael.fn.g) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Glow': {
          id: 'glow',
          icon: 'glow',
          url: 'http://www.bbc.co.uk/glow/',
          test: function(win) {
              if (win.gloader && win.gloader.getRequests) {
                  return {version: UNKNOWN_VERSION};
              }
              else if (win.glow && win.glow.dom) {
                  return {version: win.glow.VERSION || UNKNOWN_VERSION};
              }
              else if (win.Glow) {
                  return {version: win.Glow.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Socket.IO': {
          id: 'socketio',
          icon: 'socketio', // currently has no icon
          url: 'https://socket.io/',
          npm: 'socket.io',
          test: function(win) {
              // version 0.6.2 uses only io.Socket; more recent versions also have io.sockets
              if (win.io && (win.io.sockets || win.io.Socket)) {
                  return {version: win.io.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Mustache': {
          id: 'mustache',
          icon: 'mustache',
          url: 'http://mustache.github.io/',
          npm: 'mustache',
          test: function(win) {
              if (win.Mustache && win.Mustache.to_html) {
                  return {version: win.Mustache.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Fabric.js': {
          id: 'fabricjs',
          icon: 'icon38', // currently has no icon
          url: 'http://fabricjs.com/',
          npm: 'fabric',
          test: function(win) {
              if (win.fabric && win.fabric.util) {
                  return {version: win.fabric.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'FuseJS': {
          id: 'fusejs',
          icon: 'fusejs',
          url: 'http://fusejs.io/',
          npm: 'fuse.js',
          test: function(win) {
              if (win.Fuse) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Tween.js': {
          id: 'tweenjs',
          icon: 'icon38', // currently has no icon
          url: 'https://github.com/tweenjs/tween.js',
          npm: 'tween.js',
          test: function(win) {
              if (win.TWEEN && win.TWEEN.Easing) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'SproutCore': {
         id: 'sproutcore',
         icon: 'sproutcore',
         url: 'http://sproutcore.com/',
         test: function(win) {
             if (win.SC && win.SC.Application) {
                 return {version: UNKNOWN_VERSION};
             }
             return false;
         }
      },
  
      'Zepto.js': {
         id: 'zepto',
         icon: 'zepto',
         url: 'http://zeptojs.com',
         npm: 'zepto',
         test: function(win) {
             if (win.Zepto && win.Zepto.fn) {
                 return {version: UNKNOWN_VERSION};
             }
             return false;
         }
      },
  
      'three.js': {
         id: 'threejs',
         icon: 'icon38', // currently has no icon
         url: 'https://threejs.org/',
         npm: 'three',
         test: function(win) {
             if (win.THREE && win.THREE.REVISION) {
                 return {version: 'r' + win.THREE.REVISION};
             }
             else if (win.THREE) {
                 return {version: UNKNOWN_VERSION};
             }
             return false;
         }
      },
  
      'PhiloGL': {
         id: 'philogl',
         icon: 'philogl',
         url: 'http://www.senchalabs.org/philogl/',
         npm: 'philogl',
         test: function(win) {
             if (win.PhiloGL && win.PhiloGL.Camera) {
                 return {version: win.PhiloGL.version || UNKNOWN_VERSION};
             }
             return false;
         }
      },
  
      'CamanJS': {
          id: 'camanjs',
          icon: 'camanjs',
          url: 'http://camanjs.com/',
          npm: 'caman',
          test: function(win) {
              if (win.Caman && win.Caman.version) {
                  return {version: win.Caman.version.release};
              }
              else if (win.Caman) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'yepnope': {
          id: 'yepnope',
          icon: 'yepnope',
          url: 'http://yepnopejs.com/',
          test: function(win) {
              if (win.yepnope && win.yepnope.injectJs) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'LABjs': {
          id: 'labjs',
          icon: 'icon38',
          url: 'https://github.com/getify/LABjs',
          test: function(win) {
              if (win.$LAB && win.$LAB.setOptions) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'Head JS': {
          id: 'headjs',
          icon: 'headjs',
          url: 'http://headjs.com/',
          npm: 'headjs',
          test: function(win) {
              if (win.head && win.head.js) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'ControlJS': {
          id: 'controljs',
          icon: 'icon38',
          url: 'http://stevesouders.com/controljs/',
          test: function(win) {
              if (win.CJS && win.CJS.start) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'RequireJS': {
          id: 'requirejs',
          icon: 'requirejs',
          url: 'http://requirejs.org/',
          npm: 'requirejs',
          test: function(win) {
              var req = win.require || win.requirejs;
              if (req && (req.load || (req.s && req.s.contexts && req.s.contexts._ && (req.s.contexts._.loaded || req.s.contexts._.load)))) {
                  return { version: req.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'RightJS': {
          id: 'rightjs',
          icon: 'rightjs',
          url: 'http://rightjs.org/',
          test: function(win) {
              if (win.RightJS && win.RightJS.isNode) {
                  return { version: win.RightJS.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'jQuery Tools': {
         id: 'jquerytools',
         icon: 'jquerytools',
         url: 'http://jquerytools.github.io/',
         test: function(win) {
              var jq = win.jQuery || win.$;
              if(jq && jq.tools) {
                 return { version: jq.tools.version || UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'Pusher': {
         id: 'pusher',
         icon: 'pusher',
         url: 'https://pusher.com/docs/',
         npm: 'pusher-js',
         test: function(win) {
              if(win.Pusher && win.Pusher.Channel) {
                 return { version: win.Pusher.VERSION || UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'Paper.js': {
         id: 'paperjs',
         icon: 'paperjs',
         url: 'http://paperjs.org/',
         npm: 'paper',
         test: function(win) {
              if(win.paper && win.paper.Point) {
                 return { version: win.paper.version || UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'Swiffy': {
         id: 'swiffy',
         icon: 'icon38',
         url: 'https://developers.google.com/swiffy/',
         test: function(win) {
              if(win.swiffy && win.swiffy.Stage) {
                 return { version: UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'Move': {
         id: 'move',
         icon: 'move',
         url: 'https://github.com/rsms/move',
         npm: 'move',
         test: function(win) {
              if(win.move && win.move.compile) {
                 return { version: win.move.version() || UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'AmplifyJS': {
         id: 'amplifyjs',
         icon: 'amplifyjs',
         url: 'http://amplifyjs.com/',
         npm: 'amplifyjs',
         test: function(win) {
              if(win.amplify && win.amplify.publish) {
                 return { version: UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'Popcorn.js': {
         id: 'popcornjs',
         icon: 'popcornjs',
         url: 'https://github.com/mozilla/popcorn-js/',
         test: function(win) {
              if (win.Popcorn && win.Popcorn.Events) {
                 return { version: win.Popcorn.version || UNKNOWN_VERSION };
             }
             return false;
         }
      },
  
      'D3': {
          id: 'd3',
          icon: 'd3',
          url: 'https://d3js.org/',
          npm: 'd3',
          test: function(win) {
              if (win.d3 && win.d3.select) {
                  return { version: win.d3.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Handlebars': {
          id: 'handlebars',
          icon: 'handlebars',
          url: 'http://handlebarsjs.com/',
          npm: 'handlebars',
          test: function(win) {
              if(win.Handlebars && win.Handlebars.compile) {
                  return { version: win.Handlebars.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Knockout': {
          id: 'knockout',
          icon: 'knockout',
          url: 'http://knockoutjs.com/',
          npm: 'knockout',
          test: function(win) {
              if (win.ko && win.ko.applyBindings) {
                  return { version: win.ko.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Spine': {
          id: 'spine',
          icon: 'icon38',
          url: 'http://spine.github.io/',
          test: function(win) {
              if (win.Spine && win.Spine.Controller) {
                  return {version: win.Spine.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
  
      'jQuery Mobile': {
          id: 'jquery-mobile',
          icon: 'jquery_mobile',
          url: 'http://jquerymobile.com/',
          npm: 'jquery-mobile',
          test: function(win) {
              var jq = win.jQuery || win.$ || win.$jq || win.$j;
              if(jq && jq.fn && jq.fn.jquery && jq.mobile) {
                  return { version: jq.mobile.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'WebFont Loader': {
          id: 'webfontloader',
          icon: 'icon38',
          url: 'https://github.com/typekit/webfontloader',
          npm: 'webfontloader',
          test: function(win) {
              if(win.WebFont && win.WebFont.load) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Angular': {
          id: 'angular',
          icon: 'angular',
          url: 'https://angular.io/',
          npm: '@angular/core',
          test: function(win) {
              var ngVersion = win.document.querySelector('[ng-version]');
              if (ngVersion) {
                  return { version: ngVersion.getAttribute('ng-version') || UNKNOWN_VERSION };
              }
              else if (win.ng && win.ng.probe instanceof Function) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'AngularJS': {
          id: 'angularjs',
          icon: 'angularjs',
          url: 'https://angularjs.org/',
          npm: 'angular',
          test: function(win) {
              var ng = win.angular;
              if(ng && ng.version && ng.version.full) {
                  return { version: ng.version.full };
              }
              else if (ng) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Ember.js': {
          id: 'emberjs',
          icon: 'emberjs',
          url: 'https://emberjs.com/',
          npm: 'ember-source',
          test: function(win) {
              var ember = win.Ember || win.Em;
              if (ember && ember.GUID_KEY) {
                  return { version: ember.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Ember.js (Fast path)': {
          id: 'emberjs-fast',
          icon: 'emberjs',
          url: 'https://emberjs.com/',
          npm: 'ember-source',
          test: function (win) {
              var ember = win.Ember || win.Em;
              if (ember) {
                  return { version: ember.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Hammer.js': {
          id: 'hammerjs',
          icon: 'hammerjs',
          url: 'http://eightmedia.github.io/hammer.js/',
          npm: 'hammerjs',
          test: function(win) {
              if(win.Hammer && win.Hammer.Pinch) {
                  // Hammer.VERSION available in 1.0.10+
                  return { version: win.Hammer.VERSION || "&lt; 1.0.10" };
              }
              return false;
          }
      },
  
      'Visibility.js': {
          id: 'visibilityjs',
          icon: 'icon38',
          url: 'https://github.com/ai/visibilityjs',
          npm: 'visibilityjs',
          test: function(win) {
              if(win.Visibility && win.Visibility.every) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'Velocity.js': {
          id: 'velocityjs',
          icon: 'icon38',
          url: 'http://velocityjs.org/',
          npm: 'velocity-animate',
          test: function(win) {
              var jq = win.jQuery || win.$,
                  velocity = jq ? jq.Velocity : win.Velocity;
  
              if(velocity && velocity.RegisterEffect && velocity.version) {
                  return {
                      version:
                          velocity.version.major + "." +
                          velocity.version.minor + "." +
                          velocity.version.patch
                  };
              }
              else if (velocity && velocity.RegisterEffect) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
  
      'IfVisible.js': {
          id: 'ifvisiblejs',
          icon: 'icon38',
          url: 'http://serkanyersen.github.io/ifvisible.js/',
          npm: 'ifvisible.js',
          test: function(win) {
              var iv = win.ifvisible;
              if(iv && iv.__ceGUID === "ifvisible.object.event.identifier") {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Pixi.js': {
          id: 'pixi',
          icon: 'pixi',
          url: 'http://www.pixijs.com/',
          npm: 'pixi.js',
          test: function(win) {
              var px = win.PIXI;
              if(px && px.WebGLRenderer && px.VERSION) {
                  // version 4.4.3 returns simply "4.4.3"; version 1.5.2 returns "v1.5.2"
                  return { version: px.VERSION.replace('v', '') || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'DC.js': {
          id: 'dcjs',
          icon: 'dcjs',
          url: 'http://dc-js.github.io/dc.js/',
          npm: 'dc',
          test: function(win) {
              var dc = win.dc;
              if(dc && dc.registerChart) {
                  return { version: dc.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'GreenSock JS': {
          id: 'greensock',
          icon: 'greensock',
          url: 'https://greensock.com/gsap',
          npm: 'gsap',
          test: function(win) {
              if (win.TweenMax && win.TweenMax.pauseAll) {
                  return { version: win.TweenMax.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'FastClick': {
          id: 'fastclick',
          icon: 'fastclick',
          url: 'https://github.com/ftlabs/fastclick',
          npm: 'fastclick',
          test: function(win) {
              if(win.FastClick && win.FastClick.notNeeded) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Isotope': {
          id: 'isotope',
          icon: 'isotope',
          url: 'https://isotope.metafizzy.co/',
          npm: 'isotope-layout',
          test: function(win) {
              if(win.Isotope || (win.$ != null && win.$.Isotope)) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Marionette': {
          id: 'marionette',
          icon: 'marionette',
          url: 'https://marionettejs.com/',
          npm: 'backbone.marionette',
          test: function(win) {
              if(win.Marionette && win.Marionette.Application) {
                  return { version: win.Marionette.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Can': {
          id: 'canjs',
          icon: 'canjs',
          url: 'https://canjs.com/',
          npm: 'can',
          test: function (win) {
              if (win.can && win.can.Construct) {
                  return { version: win.can.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Vue': {
          id: 'vue',
          icon: 'vue',
          url: 'https://vuejs.org/',
          npm: 'vue',
          test: function(win) {
              function isVueNode(node) {
                  return node.__vue__ != null ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
              }
              var hasVueNode = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, isVueNode).nextNode() !== null;
              if (hasVueNode) {
                  return { version: win.Vue && win.Vue.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Vue (Fast path)': {
          id: 'vue-fast',
          icon: 'vue',
          url: 'https://vuejs.org/',
          npm: 'vue',
          test: function (win) {
              if (win.Vue) {
                  return { version: win.Vue && win.Vue.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Nuxt.js': {
          id: 'nuxt',
          icon: 'nuxt',
          url: 'https://nuxtjs.org/',
          npm: 'nuxt',
          test: function(win) {
              if ((win.__NUXT__ && win.__NUXT__.data != null) || win.$nuxt) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Nuxt.js (Fast path)': {
          id: 'nuxt-fast',
          icon: 'nuxt',
          url: 'https://nuxtjs.org/',
          npm: 'nuxt',
          test: function (win) {
              if (win.__NUXT__  || win.$nuxt) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Two': {
          id: 'two',
          icon: 'two',
          url: 'https://two.js.org/',
          npm: 'two.js',
          test: function(win) {
              if (win.Two && win.Two.Utils) {
                  return { version: win.Two.Version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Brewser': {
          id: 'brewser',
          icon: 'brewser',
          url: 'https://robertpataki.github.io/brewser/',
          npm: 'brewser',
          test: function(win) {
              if(win.BREWSER && win.BREWSER.ua) {
                  return { version: BREWSER.VERSION || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Material Design Lite': {
          id: 'materialdesignlite',
          icon: 'mdl',
          url: 'https://getmdl.io/',
          npm: 'material-design-lite',
          test: function(win) {
              if(win.componentHandler && win.componentHandler.upgradeElement) {
                  return { version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
      'Kendo UI': {
          id: 'kendoui',
          icon: 'kendoui',
          url: 'https://github.com/telerik/kendo-ui-core',
          npm: 'kendo-ui-core',
          test: function(win) {
              if (win.kendo && win.kendo.View && win.kendo.View.extend) {
                  return {version: win.kendo.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
      'Matter.js': {
          id: 'matterjs',
          icon: 'matter-js',
          url: 'http://brm.io/matter-js/',
          npm: 'matter-js',
          test: function(win) {
              if (win.Matter && win.Matter.Engine) {
                  return {version: UNKNOWN_VERSION};
              }
              return false;
          }
      },
      'Riot': {
          id: 'riot',
          icon: 'riot',
          url: 'http://riotjs.com/',
          npm: 'riot',
          test: function(win) {
              if (win.riot && win.riot.mixin) {
                  return { version: win.riot.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Sea.js': {
          id: 'seajs',
          icon: 'icon38',
          url: 'https://seajs.github.io/seajs/docs/',
          npm: 'seajs',
          test: function(win) {
              if(win.seajs && win.seajs.use) {
                  return { version: win.seajs.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Moment.js': {
          id: 'momentjs',
          icon: 'momentjs',
          url: 'http://momentjs.com/',
          npm: 'moment',
          test: function(win) {
              if(win.moment && (win.moment.isMoment || win.moment.lang)) {
                  // version 1.0.0 has neither "isMoment" nor "version"
                  return { version: win.moment.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Moment Timezone': {
          id: 'moment-timezone',
          icon: 'momentjs',
          url: 'http://momentjs.com/timezone/',
          npm: 'moment-timezone',
          test: function(win) {
              if (win.moment && win.moment.tz) {
                  return { version: win.moment.tz.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'ScrollMagic': {
          id: 'scrollmagic',
          icon: 'scrollmagic',
          url: 'http://scrollmagic.io/',
          npm: 'scrollmagic',
          test: function(win) {
              if (win.ScrollMagic && win.ScrollMagic.Controller) {
                  return {version: ScrollMagic.version || UNKNOWN_VERSION};
              }
              return false;
          }
      },
      'SWFObject': {
          id: 'swfobject',
          icon: 'icon38', // currently has no icon
          url: 'https://github.com/swfobject/swfobject',
          test: function(win) {
              if (win.swfobject && win.swfobject.embedSWF) {
                  // 2.x - exact version only for 2.3
                  return { version: win.swfobject.version || UNKNOWN_VERSION };
              } else if(win.deconcept && win.deconcept.SWFObject) {
                  // 1.x
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'FlexSlider': {
          id: 'flexslider',
          icon: 'icon38', // currently has no icon
          url: 'https://woocommerce.com/flexslider/',
          npm: 'flexslider',
          test: function(win) {
              var jq = win.jQuery || win.$ || win.$jq || win.$j;
              if (jq && jq.fn && jq.fn.jquery && jq.flexslider){
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'SPF': {
          id: 'spf',
          icon: 'icon38', // currently has no icon
          url: 'https://youtube.github.io/spfjs/',
          npm: 'spf',
          test: function(win) {
              if (win.spf && win.spf.init) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Numeral.js': {
          id: 'numeraljs',
          icon: 'icon38', // currently has no icon
          url: 'http://numeraljs.com/',
          npm: 'numeraljs',
          test: function(win) {
              if (win.numeral && win.isNumeral) {
                  return { version: win.numeral.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'boomerang.js': {
          id: 'boomerangjs',
          icon: 'icon38', // currently has no icon
          url: 'https://soasta.github.io/boomerang/',
          npm: 'boomerangjs',
          test: function(win) {
              if (win.BOOMR && win.BOOMR.utils && win.BOOMR.init) {
                  return { version: win.BOOMR.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Framer': {
          id: 'framer',
          icon: 'framer',
          url: 'https://framer.com/',
          npm: 'framerjs',
          test: function(win) {
              if (win.Framer && win.Framer.Layer) {
                  return { version: win.Framer.Version.build || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Marko': {
          id: 'marko',
          icon: 'marko',
          url: 'https://markojs.com/',
          npm: 'marko',
          test: function (win) {
              var selector = '[data-marko-key], [data-marko]';
              var markoElement = document.querySelector(selector);
              if (markoElement) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'AMP': {
          id: 'amp',
          icon: 'amp',
          url: 'https://amp.dev/',
          npm: 'https://www.npmjs.com/org/ampproject',
          test: function (win) {
              var version = win.document.documentElement.getAttribute("amp-version");
              return version ? { version: version } : false;
          }
      },
      'Gatsby': {
          id: 'gatsby',
          icon: 'gatsby',
          url: 'https://www.gatsbyjs.org/',
          npm: 'gatsby',
          test: function (win) {
              if (document.getElementById('___gatsby')) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Shopify': {
          id: 'shopify',
          icon: 'shopify',
          url: 'https://www.shopify.com/',
          npm: null,
          test: function (win) {
              if (win.Shopify && win.Shopify.shop) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Magento': {
          id: 'magento',
          icon: 'magento',
          url: 'https://magento.com/',
          npm: null,
          test: function (win) {
              // Same detecton used in Magento 2 DevTools: https://github.com/magento/m2-devtools
              const reRequireScript = /\/static(?:\/version\d+)?\/frontend\/.+\/.+\/requirejs\/require(?:\.min)?\.js/;
              const scripts = Array.from(document.querySelectorAll('script[src]') || []);
              if (scripts.some(s => reRequireScript.test(s.src))) {
                  return { version: 2 }; // Magento 1 is no longer supported and this only verifies version 2
              }
              
              return false;
          }
      },
      'WordPress': {
          id: 'wordpress',
          icon: 'wordpress',
          url: 'https://wordpress.org/',
          npm: null,
          test: function (win) {
              const hasAPILinkElem = !!document.querySelector('link[rel="https://api.w.org/"]');
              const hasWPIncludes = !!document.querySelectorAll('link[href*="wp-includes"], script[src*="wp-includes"]').length;
  
              if (!hasAPILinkElem && !hasWPIncludes) return false;
  
              const generatorMeta = document.querySelector('meta[name=generator][content^="WordPress"]');
              const version = generatorMeta ? generatorMeta.getAttribute("content").replace(/^\w+\s/,'') : UNKNOWN_VERSION;
              return { version };
          }
      },
      'Wix': {
          id: 'wix',
          icon: 'wix',
          url: 'https://www.wix.com/',
          npm: null,
          test: function (win) {
              if (win.wixBiSession) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Workbox': {
        id: 'workbox',
        icon: 'workbox',
        url: 'https://developers.google.com/web/tools/workbox/',
        npm: 'workbox-sw',
        test: async function (win) {
          var nav = win.navigator;
          // Service Workers not supported
          if (!('serviceWorker' in nav)) {
            return false;
          }
          return nav.serviceWorker.getRegistration()
          .then(function(registration) {
            var scriptURL = nav.serviceWorker.controller.scriptURL;
            return fetch(scriptURL, { credentials: 'include',
              headers: { 'service-worker': 'script' }
            })
            .then(function(response) {
              return response.text();
            })
            .then(function(scriptContent) {
              var workboxRegExp = /new Workbox|new workbox|workbox\.precaching\.|workbox\.strategies/gm;
              if (workboxRegExp.test(scriptContent)) {
                // Adapted from
                // https://github.com/semver/semver/issues/232#issue-48635632
                var semVerRegExp = /workbox.*?\b((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?)\b/gim;
                var matches = semVerRegExp.exec(scriptContent);
                var version = UNKNOWN_VERSION;
                if (Array.isArray(matches) && matches.length > 1 && matches[1]) {
                  version = matches[1];
                }
                return { version: version };
              }
              return false;
            });
          }).catch(function(exception) {
            return false;
          });
        }
      },
      'Boq': {
          id: 'boq',
          icon: 'icon38',
          url: 'https://github.com/johnmichel/Library-Detector-for-Chrome/pull/143',
          npm: null,
          test: function (win) {
              if (win.WIZ_global_data) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Wiz': {
          id: 'wiz',
          icon: 'icon38',
          url: 'https://github.com/johnmichel/Library-Detector-for-Chrome/pull/147',
          npm: null,
          test: function (win) {
              if (document.__wizdispatcher) {
                  return { version: UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'core-js': {
          id: 'corejs',
          icon: 'icon38',
          url: 'https://github.com/zloirock/core-js',
          npm: 'core-js',
          test: function (win) {
              const shared = win['__core-js_shared__'];
              const core = win.core;
              if (shared) {
                  const versions = shared.versions;
                  return { version: Array.isArray(versions) ? versions.map(it => `${ it.version }: ${ it.mode }`).join(', ') : UNKNOWN_VERSION };
              } else if (core) {
                  return { version: core.version || UNKNOWN_VERSION };
              }
              return false;
          }
      },
      'Create React App': {
          id: 'create-react-app',
          icon: 'cra',
          url: 'https://create-react-app.dev/',
          npm: 'react-scripts',
          test: async function (win) {
              // CRA does not have any explicit markers
              // This requests for an asset-manifest.json file that exists for mostly all v2 and v3 CRA apps
              try {
                  const response = await fetch('/asset-manifest.json');
                  const manifest = await response.json();
  
                  const hasFilesEntrypoints = manifest.files || manifest.entrypoints;
                  const containsMainBundle = manifest['main.js'] || (manifest.files && manifest.files['main.js']);
  
                  if (hasFilesEntrypoints || containsMainBundle) {
                      return { version: UNKNOWN_VERSION };
                  }
              
                  return false;
              }
              catch (err) {
                  return false;
              }
          }
      }
  };
  