You are here

modernizr.module in Modernizr 7.3

Main module file for Modernizr

File

modernizr.module
View source
<?php

/**
 * @file
 *   Main module file for Modernizr
 */

// Regular expression to determine which version of Modernizr is installed.
define('MODERNIZR_VERSION_REGEX', '/([23]\\.\\d\\.\\d)/');

// Regular expression to detect valid Modernizr filenames.
define('MODERNIZR_FILENAME_REGEX', '/^modernizr[A-Za-z0-9\\.-]*\\.js$/');

// Our drupal_add_js() and libraries_load() calls use this value to maintain
// consistency between the position of the library and its inline settings.
define('MODERNIZR_SCRIPT_GROUP', JS_LIBRARY - 10);
define('MODERNIZR_SCRIPT_WEIGHT', -100);

// As of 7.x-3.3 we support footer scope, inlining, and defer.
define('MODERNIZR_TYPE_DEFAULT', 'sync');
define('MODERNIZR_SCOPE_DEFAULT', 'header');

// Determines the severity of administrative errors.
// As of 7.x-3.7 we switched the default to TRUE since yepnope is now included
// automatically, so a custom build is no longer absolutely necessary in order
// to begin using hook_modernizr_load() functionality.
define('MODERNIZR_QUIET_DEFAULT', TRUE);

// As of 7.x-3.5 we support Modernizr v3, which cannot include yepnope.js in a
// custom build. For backward compat purposes, we will enable this flag in an
// update hook automatically, but the default it to not include it.
define('MODERNIZR_YEPNOPE_DEFAULT', FALSE);

/**
 * Default drupal_add_js settings. Used in multiple places.
 *
 * @return array An array of settings for drupal_add_js.
 */
function _modernizr_js_settings() {
  return array(
    'type' => variable_get('modernizr_type', MODERNIZR_TYPE_DEFAULT) != 'inline' ? 'file' : 'inline',
    'scope' => variable_get('modernizr_scope', MODERNIZR_SCOPE_DEFAULT),
    'group' => MODERNIZR_SCRIPT_GROUP,
    'weight' => MODERNIZR_SCRIPT_WEIGHT,
    'every_page' => TRUE,
    'preprocess' => 0,
    'defer' => variable_get('modernizr_type', MODERNIZR_TYPE_DEFAULT) == 'defer' ? TRUE : FALSE,
  );
}

/**
 * Implements hook_page_build().
 *
 * We used to use hook_init(), but that loads the JS files needlessly
 * on AJAX requests, private file requests, etc.
 */
function modernizr_page_build(&$page) {
  global $base_url;
  $modernizr_js_settings = _modernizr_js_settings();

  // Load Modernizr on the page by invoking our implementation of
  // hook_libraries_info().
  //
  // We can only use this method when Libraries API 2.0 is installed. Since Libraries 1.0
  // did not contain a function called libraries_load(), we must explicitly check for a
  // valid function to avoid fatal errors.
  //
  // @see http://drupal.org/node/1919796
  if (module_exists('libraries') && function_exists('libraries_load')) {
    libraries_load('modernizr');
  }
  else {

    // First, figure out if we're inlining.
    if (in_array(variable_get('modernizr_type', MODERNIZR_TYPE_DEFAULT), array(
      'sync',
      'defer',
    ))) {

      // We are loading external script. Load file path.
      $modernizr_file = modernizr_get_path();
    }
    else {

      // We are inlining. Load contents of file instead of path.
      $modernizr_file = file_get_contents(modernizr_get_path());
    }

    // With no Libraries API, load the regular way.
    drupal_add_js($modernizr_file, $modernizr_js_settings);
  }

  // We want yepnope() commands to be issued immediately after the call
  // to Modernizr so that they download while the page renders. The overrides
  // to $inline_js_settings will format the output as inline JS.
  if ($output = _modernizr_load_generate()) {

    // Modernizr v3 removed the ability to include yepnope.js directly in the
    // custom builds. To ensure that previous users of this module can continue
    // without breaking changes, we need to load a copy of yepnope manually,
    // which Modernizr detects and aliases to yepnope().
    if ($output && variable_get('modernizr_cb_load', MODERNIZR_YEPNOPE_DEFAULT)) {
      $yepnope_settings = $modernizr_js_settings;
      $yepnope_settings['type'] = 'inline';
      $yepnope_settings['weight'] = MODERNIZR_SCRIPT_WEIGHT - 1;

      // yepnope.js
      drupal_add_js(file_get_contents(drupal_get_path('module', 'modernizr') . '/js/yepnope.js'), $yepnope_settings);
      $inline_js_settings = $modernizr_js_settings;
      $inline_js_settings['type'] = 'inline';
      $inline_js_settings['weight'] = MODERNIZR_SCRIPT_WEIGHT + 1;

      // yepnope() statements
      drupal_add_js($output, $inline_js_settings);
    }
    else {
      if ($output && !variable_get('modernizr_cb_load', MODERNIZR_YEPNOPE_DEFAULT)) {
        drupal_add_js('console.warn("The Modernizr module is receiving requests to use yepnope.js but that option is currently disabled. Please enable yepnope.js by loading ' . $base_url . '/admin/config/development/modernizr/settings' . '");', array(
          'type' => 'inline',
        ));
      }
    }
  }
}

/**
 * Implements hook_permission().
 */
function modernizr_permission() {
  return array(
    'administer modernizr' => array(
      'title' => t('Administer Modernizr'),
      'description' => t('Perform administration tasks for Modernizr.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function modernizr_menu() {
  $items = array();

  // Rebuild Modernizr
  $items['admin/config/development/modernizr/rebuild'] = array(
    'title' => 'Rebuild Modernizr',
    'description' => 'Queries Drupal for Modernizr dependencies and generates a custom link to the Modernizr builder.',
    'page callback' => 'modernizr_generate_url',
    'file' => 'modernizr.admin.inc',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'access arguments' => array(
      'administer modernizr',
    ),
  );

  // Module settings
  $items['admin/config/development/modernizr/settings'] = array(
    'title' => 'Modernizr settings',
    'description' => 'Administrative settings for Modernizr module.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'modernizr_admin',
    ),
    'file' => 'modernizr.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'access arguments' => array(
      'administer modernizr',
    ),
  );

  // Admin menu item (duplicate of "Rebuild Modernizr")
  $items['admin/config/development/modernizr'] = array(
    'title' => 'Modernizr',
    'description' => 'Queries Drupal for Modernizr dependencies and generates a custom link to the Modernizr builder.',
    'page callback' => 'modernizr_generate_url',
    'file' => 'modernizr.admin.inc',
    'type' => MENU_NORMAL_ITEM,
    'access arguments' => array(
      'administer modernizr',
    ),
  );
  return $items;
}

/**
 * Implements hook_libraries_info().
 *
 * @return array
 */
function modernizr_libraries_info() {
  $modernizr_js_settings = _modernizr_js_settings();
  $libraries = array();
  $file_name = modernizr_get_filename();

  // Define Modernizr within Libraries API
  $libraries['modernizr'] = array(
    'name' => t('Modernizr'),
    'vendor url' => 'http://modernizr.com',
    'download url' => 'http://modernizr.com/download/',
    'version arguments' => array(
      'file' => $file_name,
      'pattern' => MODERNIZR_VERSION_REGEX,
    ),
    'files' => array(
      'js' => array(
        $file_name => $modernizr_js_settings,
      ),
    ),
  );
  return $libraries;
}

/**
 * Returns the full path of modernizr, along with the filename.
 *
 * @return string
 */
function modernizr_get_path() {
  $path =& drupal_static(__FUNCTION__);
  if ($path === NULL) {

    // Get possible paths for the file.
    $paths = _modernizr_get_paths();

    // Scan directories for files
    $path = _modernizr_scan_for_library($paths);
  }
  return $path;
}

/**
 * Helper function to scan for acceptably named libraries
 */
function _modernizr_get_paths() {
  $paths =& drupal_static(__FUNCTION__);
  if ($paths === NULL) {
    $paths = array();
    foreach (_modernizr_library_search_paths() as $search_path) {
      $library_path = $search_path . '/modernizr';
      if (file_exists($library_path)) {
        $paths[] = $library_path;
      }
    }
  }
  return $paths;
}

/**
 * Get library search paths.
 *
 * Original logic was taken from Libraries 7.x-2.3 since it doesn't provide a
 * way to look up its search paths.
 *
 * @see libraries_get_libraries()
 */
function _modernizr_library_search_paths() {
  $searchdir = array();
  $profile = drupal_get_path('profile', drupal_get_profile());
  $config = conf_path();

  // Similar to 'modules' and 'themes' directories in the root directory,
  // certain distributions may want to place libraries into a 'libraries'
  // directory in Drupal's root directory.
  $searchdir[] = 'libraries';

  // Always search sites/all/libraries.
  $searchdir[] = 'sites/all/libraries';

  // $profile should never be empty in a proper Drupal setup. Check to make sure
  // it exists before adding path.
  if ($profile) {

    // Similar to 'modules' and 'themes' directories inside an installation
    // profile, installation profiles may want to place libraries into a
    // 'libraries' directory.
    $searchdir[] = $profile . '/libraries';
  }

  // $config should never be empty in a proper Drupal setup. Check to make sure
  // it exists before adding path.
  if ($config) {

    // Also search sites/<domain>/*.
    $searchdir[] = $config . '/libraries';
  }
  return $searchdir;
}

/**
 * Helper function to scan for acceptably named libraries
 */
function _modernizr_scan_for_library($paths) {
  $path = '';
  if (is_array($paths) && !empty($paths)) {
    foreach ($paths as $p) {
      if ($files = file_scan_directory($p, MODERNIZR_FILENAME_REGEX)) {
        $path = reset($files)->uri;
        break;
      }
    }
  }
  return $path;
}

/**
 * Helper function to fetch the active Modernizr library.
 */
function modernizr_get_filename() {

  // Get the full path to the library,
  $full_path = modernizr_get_path();

  // Break it up into its directories and file
  $file_parts = explode('/', $full_path);

  // Isolate the filename
  $file_name = $file_parts[count($file_parts) - 1];
  return $file_name;
}

/**
 * Guesses the modernizr library version.
 *
 * This function is using a regex, which assumes that the format of the version
 * string won't change. If it changes, feel free to submit a bug report.
 *
 * @return mixed The version number if exists, or a boolean FALSE if it can't be
 * determined.
 */
function modernizr_get_version($reset = FALSE) {
  $version =& drupal_static(__FUNCTION__);
  if ($version === NULL || $reset == TRUE) {
    if ($cached = cache_get('modernizr_version') && isset($cached->data) && $reset != TRUE) {
      $version = $cached->data;
    }
    else {
      $version = FALSE;
      $modernizr_path = modernizr_get_path();
      if (file_exists($modernizr_path)) {
        $modernizr = file_get_contents($modernizr_path);
        $matches = array();
        preg_match(MODERNIZR_VERSION_REGEX, $modernizr, $matches);
        if (isset($matches[0])) {
          $version = $matches[0];
          if ($version) {
            cache_set('modernizr_version', $version);
          }
        }
        unset($modernizr);
      }
    }
  }
  return $version;
}

/**
 * Implements MODULE_preprocess_html().
 */
function modernizr_preprocess_html(&$vars, $hook) {

  // This will set up all of our tests for Modernizr.
  modernizr_load_data();
}

/**
 * A function to generate the load data from the current themes.
 *
 * Reads async-loaded CSS/JS from theme .info files. Stores info in variable.
 * Prints yepnope() calls into drupal_add_js() as inline settings.
 *
 * @return array
 */
function modernizr_load_data() {
  $load =& drupal_static(__FUNCTION__);
  if (!isset($load)) {

    // This is the first time this is called.
    global $base_url, $base_theme_info, $theme_info;
    $load = array();
    $num_tests = 0;

    // Make a list of base themes and the current theme.
    $themes = $base_theme_info;
    $themes[] = $theme_info;
    foreach (array_keys($themes) as $key) {
      $theme_path = dirname($themes[$key]->filename) . '/';
      if (isset($themes[$key]->info['modernizr'])) {

        // Loop through Modernizr calls and assemble Load variable.
        foreach (array_keys($themes[$key]->info['modernizr']) as $test_key => $test) {

          // If no tests are defined, simply add them as resources for loading them unconditionally.
          if (is_numeric($test)) {
            $load[] = array(
              _modernizr_sanitize_resource($themes[$key]->info['modernizr'][$test_key], $theme_path),
            );
          }
          elseif ($test != 'tests') {

            // All other entries inside a theme's modernizr[] settings should be scanned
            $load[$num_tests]['test'] = $test;
            foreach (array_keys($themes[$key]->info['modernizr'][$test]) as $action) {
              foreach ($themes[$key]->info['modernizr'][$test][$action] as $asset) {

                // First figure out which property we're reading.
                // callback/complete need different processing than yep/nope/both/load
                $functions = array(
                  'callback',
                  'complete',
                );

                // Is this a function or a resource?
                if (in_array($action, $functions)) {

                  // It's a function
                  $load[$num_tests][$action][] = _modernizr_sanitize_callback($asset);
                }
                else {

                  // It's a resource
                  $load[$num_tests][$action][] = _modernizr_sanitize_resource($asset, $theme_path);
                }
              }
            }
            $num_tests++;
          }
        }
      }
    }
  }
  return $load;
}

/**
 * Helper function to render the yepnope() calls.
 */
function _modernizr_load_generate() {
  $output = FALSE;

  // Get yepnope() calls from the active theme.
  $theme = modernizr_load_data();

  // Collect data from modules that implement hook_modernizr_load().
  $modules = modernizr_load_list();

  // Combine the data from the .info file and the Drupal modules.
  // Themes go first because they are more visual and in most cases
  // it's probably best to load them first. Modules whose assets
  // truly need to be loaded first have hook_modernizr_load_alter()
  // at their disposal.
  $test_objects = array_merge($theme, $modules);

  // Build the yepnope() commands.
  if (count($test_objects)) {
    $num_tests = 0;
    $items = array();
    foreach ($test_objects as $load) {

      // If test is defined, this entry will be an object.
      if (isset($load['test'])) {
        $item = '{' . "\n";
        $item .= '  test: ' . $load['test'] . ',' . "\n";

        // Print each action and its resources
        $actions = array(
          'yep',
          'nope',
          'both',
          'load',
        );
        foreach ($actions as $action) {
          if (isset($load[$action])) {

            // Begin output for this action
            $item .= '  ' . sprintf('%-4s', $action) . ': ';

            // How many resources for this action?
            if (count($load[$action]) == 1) {

              // Single resource
              $item .= "'" . $load[$action][0] . "',\n";
            }
            else {

              // Multiple resources
              $item .= '[';
              foreach ($load[$action] as $resource) {
                $item .= "'" . $resource . "',";
              }

              // Truncate last comma
              $item = substr($item, 0, -1);
              $item .= "],\n";
            }
          }
        }

        // Output these two properties without quotes around the output
        $callbacks = array(
          'callback',
          'complete',
        );
        foreach ($callbacks as $action) {
          if (isset($load[$action])) {

            // Begin output for this action
            $item .= '  ' . sprintf('%-4s', $action) . ': ';

            // How many callbacks for this action?
            if (count($load[$action]) == 1) {

              // Single resource
              $item .= $load[$action][0] . ",\n";
            }
            else {

              // Multiple resources
              $item .= '[';
              foreach ($load[$action] as $callback) {
                $item .= $callback . ",";
              }

              // Truncate last comma
              $item = substr($item, 0, -1);
              $item .= "],\n";
            }
          }
        }

        // Truncate last comma and newline
        $item = substr($item, 0, -2);
        $item .= "\n}";
        $num_tests++;
      }
      else {
        $resources = array();
        foreach ($load as $resource) {
          $resources[] = "'" . $resource . "'";
        }
        $item = implode(",\n", $resources);
        $num_tests++;
      }
      $items[] = $item;
    }
    $output .= 'yepnope(';

    // Issue commands as array if there is more than resource to load.
    $output .= $num_tests > 1 ? '[' : '';

    // Add commands.
    $output .= implode(",\n", $items);

    // Finally, close the yepnope() function parenthesis.
    $output .= $num_tests > 1 ? ']' : '';
    $output .= ');';
  }
  return $output;
}

/**
 * Implements MODULE_preprocess_maintenance_page().
 */
function modernizr_preprocess_maintenance_page(&$vars, $hook) {
  modernizr_preprocess_html($vars, $hook);
}

/**
 * Helper function to sanitize yepnope() callbacks
 */
function _modernizr_sanitize_callback($callback) {
  global $base_url;
  $output = '';
  $function_regex = '/^function(\\s)*\\(\\)(\\s)*\\{(.*)\\}$/';

  // Save the people who don't wrap their code in anonymous functions.
  // Yes, an extra semi-colon has been added for safety :)
  $output = preg_match($function_regex, $callback) ? $callback : 'function(){' . $callback . ';}';
  return $output;
}

/**
 * Helper function to sanitize yepnope() assets
 */
function _modernizr_sanitize_resource($resource, $theme_path) {
  global $base_path, $base_url;
  $output = '';

  // If a path starts with 'sites/' or 'profiles/' we assume they know exactly
  // where they're going. Otherwise, they seem like relative URLs so append
  // theme path.
  $output = strpos($resource, 'sites/') === 0 || strpos($resource, 'profiles/') === 0 ? $base_path . $resource : $base_url . '/' . $theme_path . $resource;
  return $output;
}

/**
 * Helper function for hook_modernizr_info().
 * Returns a Modernizr argument's type.
 */
function _modernizr_get_type($arg) {
  $data = _modernizr_get_arg_info($arg, 'type');

  // Since community-created detects are by far the most likely unknown entry,
  // we assume that a value not found in modernizr.args.inc is a community detect.
  // Note: 'tests' does NOT need t() because it is a machine value.
  return $data ? $data : 'tests';
}

/**
 * Helper function for hook_modernizr_info().
 * Returns a Modernizr argument's description.
 */
function _modernizr_get_desc($arg) {
  $data = _modernizr_get_arg_info($arg, 'desc');

  // If we can't find a description, just admit it.
  return $data ? $data : '<em>' . t('No description available.') . '</em>';
}

/**
 * A helper function to get the information stored in modernizr.args.inc.
 *
 * @param string $arg
 *   The test machine name.
 * @param string $type (default: 'desc')
 *   The data wanted, currently just 'desc' or 'type'.
 * @return
 *   The data in the field, or FALSE if it doesn't exist.
 */
function _modernizr_get_arg_info($arg, $type = 'desc') {
  static $loaded = FALSE;
  if (!$loaded) {
    $loaded = module_load_include('inc', 'modernizr', 'modernizr.args');
  }
  $data = _modernizr_args_return($arg);

  // This data doesnt exist.
  return $data && isset($data[$type]) ? $data[$type] : FALSE;
}

/**
 * Helper function to pulls all tests from the current modernizr.js
 */
function _modernizr_current_build() {
  $tests =& drupal_static(__FUNCTION__);
  if (!isset($tests)) {
    $path = modernizr_get_path();
    $path_parts = explode('/', $path);
    $file = $path ? file_get_contents($path) : NULL;
    $filename = $path_parts[count($path_parts) - 1];
    $tests = array();

    // $matches holds two items:
    // - [0] the full URL
    // - [1] a string containing the args captured in the parens  vvvv
    $build_url = preg_match('/https?:\\/\\/modernizr.com\\/download\\/[#?]-(.*) /', $file, $matches);

    // Turn URL args into test entries for Drupal module
    if (isset($matches[1])) {
      $args_and_prefix = explode(':', $matches[1]);
      $build_args = explode('-', $args_and_prefix[0]);
      foreach ($build_args as $arg) {
        $tests[] = $arg;
      }
    }
    else {

      // Modernizr must not be downloaded, return null.
      return NULL;
    }
  }
  return $tests;
}

/**
 * Asks other Drupal modules which Modernizr tests they need.
 *
 * @return array
 */
function modernizr_api_list() {
  $tests =& drupal_static(__FUNCTION__);
  if (!isset($tests)) {

    // Grab all module implementations
    // Note: this is a slightly augmented version of module_invoke_all(), so
    // that we can know which module is providing which test.
    $hook = 'modernizr_info';
    foreach (module_implements($hook) as $module) {
      $function = $module . '_' . $hook;
      if (function_exists($function)) {
        $result = call_user_func($function);
        if (isset($result) && is_array($result)) {
          $tests[$module] = $result;
        }
      }
    }

    // Grabbing the information with an hook_alter is not enough for themes
    // because they will not all be active, nor their code added into the session.
    $themes = list_themes();
    $active_themes = array();
    foreach ($themes as $theme_name => $theme) {
      if ($theme->status == 1) {
        $active_themes[$theme_name] = $theme;
        if (isset($theme->base_themes)) {
          foreach ($theme->base_themes as $base_theme_name => $base_theme) {
            $active_themes[$base_theme_name] = $themes[$base_theme_name];
          }
        }
      }
    }

    // We now go into every active theme and pull from the .info file the tests.
    foreach ($active_themes as $active_theme) {
      $data = drupal_parse_info_file($active_theme->filename);
      if (isset($data['modernizr']) && isset($data['modernizr']['tests'])) {

        // There are modernizr tests within this theme.
        $theme_name = $data['name'];
        $tests[$theme_name] = $data['modernizr']['tests'];
      }
    }

    // The last thing we do is send it to have its data cleaned and organized.
    $tests = _modernizr_api_list_clean($tests);
  }
  return $tests;
}

/**
 * Cleans up the array of tests to be unified.
 *
 * @param $raw_tests array
 *  An array of tests provided by hook_modernizr_info.
 * @return array
 */
function _modernizr_api_list_clean($raw_tests) {
  $clean_tests = array();
  foreach ($raw_tests as $module => $tests) {
    foreach ($tests as $name => $data) {

      // First, we check and correct if the tests have been added using indexed
      // arrays, fixing the name variable.
      if (is_int($name) && !is_array($data)) {

        // The test is stored as a simple array, therefore the data is the name.
        $name = $data;
        $data = array();
      }
      elseif (is_int($name) && is_array($data)) {

        // Still stored as a indexed array, but the data is an array.
        $name = $data['name'];
      }

      // Now, we add these tests to our array of cleaned up data.
      if (isset($clean_tests[$name])) {

        // We already have the test, we are just going to add our module name.
        $clean_tests[$name]['source'][] = $module;
      }
      else {

        // The test has not been marked, we are adding it to the array.
        $clean_tests[$name] = $data;
        $clean_tests[$name]['source'] = array(
          $module,
        );
      }
    }
  }

  // Cleaning up the data to ensure all data we need is present.
  foreach ($clean_tests as $name => $clean_test) {
    $data = array(
      'name' => $name,
      'desc' => _modernizr_get_desc($name),
      'docs' => '',
      'camiuse' => '',
    );
    $clean_tests[$name] = array_merge($data, $clean_test);
  }
  return $clean_tests;
}

/**
 * Implements hook_modernizr_info().
 *
 * This function implements our own hook to ensure that any custom Modernizr
 * builds downloaded from either the settings screen or drush commands contain
 * the essential components needed to support the module's functionality.
 *
 * html5shiv w/ printshiv
 * - Includes some utility JS that allows IE to recognize HTML5 elements.
 */
function modernizr_modernizr_info() {
  $items = array();

  // If a site admin has chosen to require printshiv, add it to dependencies.
  if (variable_get('modernizr_cb_printshiv', FALSE)) {
    $items[] = 'printshiv';
  }
  return $items;
}

/**
 * Asks other Drupal modules for yepnope() commands.
 *
 * @return array
 */
function modernizr_load_list($reset = FALSE) {
  $load =& drupal_static(__FUNCTION__);
  if (!isset($load) || $reset) {
    $load = module_invoke_all('modernizr_load');
    drupal_alter('modernizr_load', $load);
  }
  return $load;
}

/**
 * Private function to look for missing Modernizr tests.
 */
function _modernizr_info_missing_tests() {
  $requested_tests = modernizr_api_list();
  $current_build = _modernizr_current_build();
  $missing_tests = array();
  if (is_null($current_build)) {

    // There is no installed version of Modernizr. Return all tests.
    return $requested_tests;
  }
  foreach ($requested_tests as $test => $test_info) {
    if (!in_array($test, $current_build)) {
      $missing_tests[$test] = $test_info;
    }
  }
  return $missing_tests;
}

Functions

Namesort descending Description
modernizr_api_list Asks other Drupal modules which Modernizr tests they need.
modernizr_get_filename Helper function to fetch the active Modernizr library.
modernizr_get_path Returns the full path of modernizr, along with the filename.
modernizr_get_version Guesses the modernizr library version.
modernizr_libraries_info Implements hook_libraries_info().
modernizr_load_data A function to generate the load data from the current themes.
modernizr_load_list Asks other Drupal modules for yepnope() commands.
modernizr_menu Implements hook_menu().
modernizr_modernizr_info Implements hook_modernizr_info().
modernizr_page_build Implements hook_page_build().
modernizr_permission Implements hook_permission().
modernizr_preprocess_html Implements MODULE_preprocess_html().
modernizr_preprocess_maintenance_page Implements MODULE_preprocess_maintenance_page().
_modernizr_api_list_clean Cleans up the array of tests to be unified.
_modernizr_current_build Helper function to pulls all tests from the current modernizr.js
_modernizr_get_arg_info A helper function to get the information stored in modernizr.args.inc.
_modernizr_get_desc Helper function for hook_modernizr_info(). Returns a Modernizr argument's description.
_modernizr_get_paths Helper function to scan for acceptably named libraries
_modernizr_get_type Helper function for hook_modernizr_info(). Returns a Modernizr argument's type.
_modernizr_info_missing_tests Private function to look for missing Modernizr tests.
_modernizr_js_settings Default drupal_add_js settings. Used in multiple places.
_modernizr_library_search_paths Get library search paths.
_modernizr_load_generate Helper function to render the yepnope() calls.
_modernizr_sanitize_callback Helper function to sanitize yepnope() callbacks
_modernizr_sanitize_resource Helper function to sanitize yepnope() assets
_modernizr_scan_for_library Helper function to scan for acceptably named libraries

Constants