Drupal: dodan modul Modernizer

This commit is contained in:
Robert 2021-02-05 10:37:56 +01:00
parent 5c8d6b4c17
commit 740157b6ba
13 changed files with 2319 additions and 0 deletions

View File

@ -0,0 +1,3 @@
/*! modernizr 3.6.0 (Custom Build) | MIT *
* https://modernizr.com/download/?-webp-setclasses !*/
!function(e,n,A){function o(e){var n=u.className,A=Modernizr._config.classPrefix||"";if(c&&(n=n.baseVal),Modernizr._config.enableJSClass){var o=new RegExp("(^|\\s)"+A+"no-js(\\s|$)");n=n.replace(o,"$1"+A+"js$2")}Modernizr._config.enableClasses&&(n+=" "+A+e.join(" "+A),c?u.className.baseVal=n:u.className=n)}function t(e,n){return typeof e===n}function a(){var e,n,A,o,a,i,l;for(var f in r)if(r.hasOwnProperty(f)){if(e=[],n=r[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(A=0;A<n.options.aliases.length;A++)e.push(n.options.aliases[A].toLowerCase());for(o=t(n.fn,"function")?n.fn():n.fn,a=0;a<e.length;a++)i=e[a],l=i.split("."),1===l.length?Modernizr[l[0]]=o:(!Modernizr[l[0]]||Modernizr[l[0]]instanceof Boolean||(Modernizr[l[0]]=new Boolean(Modernizr[l[0]])),Modernizr[l[0]][l[1]]=o),s.push((o?"":"no-")+l.join("-"))}}function i(e,n){if("object"==typeof e)for(var A in e)f(e,A)&&i(A,e[A]);else{e=e.toLowerCase();var t=e.split("."),a=Modernizr[t[0]];if(2==t.length&&(a=a[t[1]]),"undefined"!=typeof a)return Modernizr;n="function"==typeof n?n():n,1==t.length?Modernizr[t[0]]=n:(!Modernizr[t[0]]||Modernizr[t[0]]instanceof Boolean||(Modernizr[t[0]]=new Boolean(Modernizr[t[0]])),Modernizr[t[0]][t[1]]=n),o([(n&&0!=n?"":"no-")+t.join("-")]),Modernizr._trigger(e,n)}return Modernizr}var s=[],r=[],l={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var A=this;setTimeout(function(){n(A[e])},0)},addTest:function(e,n,A){r.push({name:e,fn:n,options:A})},addAsyncTest:function(e){r.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=l,Modernizr=new Modernizr;var f,u=n.documentElement,c="svg"===u.nodeName.toLowerCase();!function(){var e={}.hasOwnProperty;f=t(e,"undefined")||t(e.call,"undefined")?function(e,n){return n in e&&t(e.constructor.prototype[n],"undefined")}:function(n,A){return e.call(n,A)}}(),l._l={},l.on=function(e,n){this._l[e]||(this._l[e]=[]),this._l[e].push(n),Modernizr.hasOwnProperty(e)&&setTimeout(function(){Modernizr._trigger(e,Modernizr[e])},0)},l._trigger=function(e,n){if(this._l[e]){var A=this._l[e];setTimeout(function(){var e,o;for(e=0;e<A.length;e++)(o=A[e])(n)},0),delete this._l[e]}},Modernizr._q.push(function(){l.addTest=i}),Modernizr.addAsyncTest(function(){function e(e,n,A){function o(n){var o=n&&"load"===n.type?1==t.width:!1,a="webp"===e;i(e,a&&o?new Boolean(o):o),A&&A(n)}var t=new Image;t.onerror=o,t.onload=o,t.src=n}var n=[{uri:"data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=",name:"webp"},{uri:"data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==",name:"webp.alpha"},{uri:"data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA",name:"webp.animation"},{uri:"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=",name:"webp.lossless"}],A=n.shift();e(A.name,A.uri,function(A){if(A&&"load"===A.type)for(var o=0;o<n.length;o++)e(n[o].name,n[o].uri)})}),a(),o(s),delete l.addTest,delete l.addAsyncTest;for(var p=0;p<Modernizr._q.length;p++)Modernizr._q[p]();e.Modernizr=Modernizr}(window,document);

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,57 @@
Modernizr for Drupal
====================
This module implements Modernizr, the client-side feature detection
library. Modernizr allows you to avoid user-agent sniffing on the
server, and rely on the honesty of the browsers that visit your
website by detecting each individual feature that they support.
Modernizr will inject yes/no classes into your <html> tag for each
test, so that you can write conditional rules based on the results:
.multiplebgs div p {
/* properties for browsers that
support multiple backgrounds */
}
.no-multiplebgs div p {
/* optional fallback properties
for browsers that don't */
}
Modernizr v2 optionally includes a script loader which can load
additional resources based on the outcome of specific Modernizr
tests you're interested in:
Modernizr.load({
test : Modernizr.geolocation,
yep : 'normal.js',
nope : ['polyfill.js', 'wrapper.js']
});
The 3.x branch of the Drupal module integrates Modernizr.load()
so it can be used by themes/modules that support HTML5/CSS3.
Documentation
=============
Read about Modernizr: http://www.modernizr.com/docs/
Module documentation: http://drupal.org/node/1913744
Installation & Usage
====================
1. Install module
2. Build Modernizr at /admin/config/development/modernizr
3. Place your custom build inside sites/all/libraries/modernizr
Credits
=======
Project page: http://drupal.org/project/modernizr
Library page: http://modernizr.com
Module originally written by:
Tamás Demeter-Haludka - http://drupal.org/user/372872
Maintainers:
Chris Ruppel - http://drupal.org/user/411999

View File

@ -0,0 +1,41 @@
/**
* @file
* Administrative CSS for Modernizr module.
*/
body.page-admin-config-development-modernizr .modernizr-tests {
margin-left: 2em;
}
body.page-admin-config-development-modernizr .modernizr-tests h3 {
float: left;
clear: left;
margin: 0 1em 1em 0;
}
body.page-admin-config-development-modernizr .modernizr-tests p.desc {
float: left;
margin: 0;
}
body.page-admin-config-development-modernizr div.download-modernizr {
float: none;
clear: both;
padding-top: 1em;
}
/**
* Styles for Test API. Based on whether our current Modernizr lib is in sync
* with the latest Test API settings.
*/
body.page-admin-config-development-modernizr .modernizr-tests h3.not-included {
font-weight: bold;
color: #d02;
}
body.page-admin-config-development-modernizr .modernizr-tests h3.not-included::after {
content: " (missing)";
font-size: .7em;
vertical-align: top;
position: relative;
top: -2px;
}

View File

@ -0,0 +1,99 @@
<?php
/**
* @file
* drush integration for modernizr.
*/
/**
* Implements hook_drush_command().
*
* In this hook, you specify which commands your
* drush module makes available, what it does and
* description.
*
* Notice how this structure closely resembles how
* you define menu hooks.
*
* For a list of recognized keys,
* @see drush_parse_command()
*
* @return
* An associative array describing your command(s).
*/
function modernizr_drush_command() {
$items = array();
$items['modernizr-dev'] = array(
'callback' => '_modernizr_drush_download_dev',
'description' => dt('This command used to download a development copy of Modernizr but it is no longer offered on modernizr.com as of v3'),
'aliases' => array('mdl'),
);
$items['modernizr-build'] = array(
'callback' => '_modernizr_drush_custom_build',
'description' => dt('Requests a custom build of Modernizr based on your Drupal module settings. Depends on node.js/npm.'),
'aliases' => array('mcb'),
'arguments' => array(),
);
return $items;
}
/**
* Implements hook_drush_help().
*
* This function is called whenever a drush user calls
* 'drush help <name-of-your-command>'
*
* @param
* A string with the help section (prepend with 'drush:')
*
* @return
* A string with the help text for your command.
*/
function modernizr_drush_help($section) {
switch ($section) {
case 'error:modernizr-dev':
case 'drush:modernizr-dev':
return dt('This command used to download a development copy of Modernizr but it is no longer offered on modernizr.com as of v3');
case 'drush:modernizr-build':
return dt('Queries Drupal modules for any Modernizr tests they require, and creates a request for a node.js-powered CLI builder. You must install node.js, npm, and the CLI builder beforehand.');
}
}
/**
* Helper function downloads the uncompressed development copy of Modernizr.
*/
function _modernizr_drush_download_dev() {
return drush_set_error('modernizr-dev');
}
/**
* Helper function that generates a list of Modernizr tests
* from other modules and sends them to the node.js CLI builder.
*/
function _modernizr_drush_custom_build() {
$output_args = array();
$args = modernizr_api_list();
$output = '';
// Get the map of Modernizr args.
include_once(drupal_get_path('module', 'modernizr') . '/modernizr.args.inc');
// Fetch all the tests, and record which modules supplied them.
foreach ($args as $key => $test) {
$meta = _modernizr_args_return($key);
$type = $meta['type'];
$output_args[$type][] = $key;
}
// Collapse tests into the format accepted by the node builder.
$tests = (isset($output_args['tests'])) ? ' -t ' . implode(' ', $output_args['tests']) : '';
$extras = (isset($output_args['extras'])) ? ' -e ' . implode(' ', $output_args['extras']) : '';
$groups = (isset($output_args['groups'])) ? ' -g ' . implode(' ', $output_args['groups']) : '';
$not = (isset($output_args['not'])) ? ' -n ' . implode(' ', $output_args['not']) : '';
$output = $tests . $extras . $groups . $not;
return $output;
}

View File

@ -0,0 +1,5 @@
/*!
* yepnope1.5.4
* (c) WTFPL, GPLv2
*/
(function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}})(this,document);

View File

@ -0,0 +1,264 @@
<?php
/**
* @file
* Admin include for Modernizr module.
*/
/**
* Implements hook_admin().
*
* Modernizr administration settings
*/
function modernizr_admin() {
$form = array();
// Fieldset for drupal_add_js() options.
$form['js'] = array(
'#type' => 'fieldset',
'#title' => t('Placement and Performance'),
);
// Option to set the scope of Modernizr.
$form['js']['modernizr_scope'] = array(
'#type' => 'select',
'#title' => t('Where should Modernizr be loaded?'),
'#options' => array(
'header' => t('header'),
'footer' => t('footer'),
),
'#default_value' => variable_get('modernizr_scope', MODERNIZR_SCOPE_DEFAULT),
'#description' => t('When possible, it is recommended to print all JavaScript in the footer unless you are using a specific set of features which require blocking execution in the &lt;head&gt;. <a href="@url">Read more on GitHub</a>. <strong>Important:</strong> you should not move Modernizr to the bottom of the page unless ALL dependent scripts are also after Modernizr (higher weight in <code>drupal_add_js()</code> settings).', array('@url' => 'https://github.com/Modernizr/Modernizr/issues/878#issuecomment-41448059')),
);
// Options to determine how Modernizr is included. Although these options are
// presented as one group, they control two settings within drupal_add_js()
// because an inline file cannot be deferred. If inline is set, it precludes
// us from setting `defer` to TRUE. Conversely if `defer` is chosen, we must
// set the type to `file` when invoking drupal_add_js().
$form['js']['modernizr_type'] = array(
'#type' => 'select',
'#title' => t('How should Modernizr be loaded?'),
'#options' => array(
'defer' => t('Defer'),
'inline' => t('Inline'),
'sync' => t('Synchronous'),
),
'#default_value' => variable_get('modernizr_type', MODERNIZR_TYPE_DEFAULT),
'#description' => t('When possible, it is recommended to <code>defer</code> this JavaScript unless you are using a specific set of features which require blocking execution in the &lt;head&gt;. <strong>Important:</strong> you should not defer Modernizr unless any dependent scripts are also deferred.<br><br>In some cases, it might be beneficial to inline this JavaScript file. Make sure that you can confirm that this works better for your site by measuring performance! <a href="@url">Read more on GitHub</a>.', array('@url' => 'https://github.com/Modernizr/Modernizr/issues/878#issuecomment-41448059')),
);
// Fieldset for custom build options.
$form['build_options'] = array(
'#type' => 'fieldset',
'#title' => t('Custom Build Options'),
);
// Custom builds no longer require printshiv by default.
$form['build_options']['modernizr_cb_printshiv'] = array(
'#type' => 'checkbox',
'#title' => t('Require <code>printshiv</code> when custom builds are created.'),
'#default_value' => variable_get('modernizr_cb_printshiv', FALSE),
);
// Modernizr v3 deprecated direct inclusion of Modernizr.load(). In order to
// continue using Modernizr.load(), we have to include yepnope.js ourselves.
$form['build_options']['modernizr_cb_load'] = array(
'#type' => 'checkbox',
'#title' => t('Include <code>Modernizr.load()</code> functionality. Modernizr v3 no longer includes this script itself. <a href="@url">Read more on GitHub</a>.', array('@url' => 'https://github.com/Modernizr/Modernizr/issues/1182')),
'#default_value' => variable_get('modernizr_cb_load', MODERNIZR_YEPNOPE_DEFAULT),
);
// Fieldset for reporting options.
$form['reporting'] = array(
'#type' => 'fieldset',
'#title' => t('Error reporting'),
);
// Reduce severity of requirements errors. Admin can use this option to avoid
// seeing the red boxes when Modernizr requirements are not met.
$form['reporting']['modernizr_quiet'] = array(
'#type' => 'checkbox',
'#title' => t('Decrease severity of Modernizr Test API errors.'),
'#description' => t('Check this box if you\'d rather not see the red warning about missing Modernizr tests (or lack of a custom build). Enabling this option will not make Modernizr function properly if things are missing, but it will suppress the error message.'),
'#default_value' => variable_get('modernizr_quiet', MODERNIZR_QUIET_DEFAULT),
);
return system_settings_form($form);
}
/**
* Generates new Modernizr URL for admin interface
* Callback for 'admin/config/development/modernizr'.
*/
function modernizr_generate_url() {
// Reset our lists of needed Modernizr tests in drupal_static.
drupal_static_reset('modernizr_api_list');
// Get latest tests from modules and themes
$tests = modernizr_api_list();
// Begin assembling link to re-download Modernizr
$link = 'https://modernizr.com/download/?';
// Pull tests that are currently set.
$current_tests = _modernizr_current_build();
if (is_null($current_tests)) {
// We can't find a custom build of modernizr.
// Decide how severe this warning is based on admin settings.
$modernizr_severity = (variable_get('modernizr_quiet', MODERNIZR_QUIET_DEFAULT)) ? 'warning' : 'error';
// Set error/warning message.
drupal_set_message(t("You don't seem to have a custom build of Modernizr installed yet, or we are detecting the wrong version. Remove any existing modernizr-latest.js or modernizr custom builds from !path and replace it with a new copy. This page will help generate one for you.", array(
'!path' => module_exists('libraries') ? libraries_get_path('modernizr') : 'sites/all/libraries/modernizr'
)), $modernizr_severity);
}
else {
// Generate the list of tests that are being requested by the Test API, but
// are NOT in the Modernizr JS file.
$missing_tests = array_diff_key($tests, array_flip($current_tests));
foreach ($current_tests as $current_test) {
// Adds all current tests to the array of tests.
if (!isset($tests[$current_test])) {
$tests[$current_test] = array(
'name' => $current_test,
'source' => array(modernizr_get_filename()),
'desc' => _modernizr_get_desc($current_test),
'docs' => '',
'caniuse' => '',
);
}
}
}
// Create indexes for first download link/desc to place them
// above everything. They will be populated later.
$elements['download_modernizr1']['link'] = array();
$elements['download_modernizr1']['description'] = array();
// Give a hint about which file is currently in use and in which directories
// we have searched for the file.
$file_path = modernizr_get_path();
$file_markup = $file_path ? l($file_path, $file_path) : t('No file found');
$elements['modernizr_file']['title'] = array(
'#type' => 'html_tag',
'#value' => t('Currently loaded file'),
'#tag' => 'h2',
);
$elements['modernizr_file']['file'] = array(
'#type' => 'markup',
'#markup' => $file_markup,
);
if (!$file_path) {
$elements['modernizr_file']['paths'] = array(
'#theme' => 'item_list',
'#title' => t('Scanned directories'),
'#items' => _modernizr_get_paths(),
);
}
// Create the tests heading render element.
$elements['tests']['heading-tests'] = array(
'#theme' => 'html_tag',
'#value' => t('Current Modernizr Tests'),
'#tag' => 'h2',
);
// Create the tests description render element.
$elements['tests']['description'] = array(
'#theme' => 'html_tag',
'#value' => t('Currently enabled Drupal modules and themes have requested the following Modernizr tests:'),
'#tag' => 'p',
);
// Create a container to indent everything
$elements['tests']['list'] = array(
'#prefix' => '<div class="modernizr-tests">',
'#suffix' => '</div>',
);
// Check to see if there are any registered tests.
if (!empty($tests)) {
// Loop through each registered test.
foreach ($tests as $key => $test) {
// API was changed between 7.x-3.0 and 7.x-3.1. We originally specified
// `module` but since themes can also specify tests the attribute was
// changed to `source`.
$source = (isset($test['source'])) ? $test['source'] : $test['module'];
// Check to see if this test has been set. If not, add it.
if (!isset($elements['tests']['list'][$key])) {
// Check if this test is missing, and apply a special class only when it
// is missing from the current build of Modernizr JS file.
$not_included = (isset($missing_tests[$key])) ? 'not-included' : '';
// Build the element for this Modernizr test.
$elements['tests']['list'][$key]['name'] = array(
'#theme' => 'html_tag',
'#value' => $key,
'#tag' => 'h3',
'#attributes' => array('class' => $not_included),
);
}
// Create the description for this test.
$elements['tests']['list'][$key]['tests'][] = array(
'description' => array(
'#markup' => _modernizr_get_desc($key),
'#prefix' => '<p class="desc">',
'#suffix' => '</p>',
),
);
// @TODO: Check to see if this test has already been added by another module.
$link .= $key . '-';
}
}
else {
$elements['tests']['list']['#markup'] = '<p>There are no Modernizr tests registered</p>';
}
// Create the download link render element.
$download_link = array(
'#prefix' => '<div class="download-modernizr">',
'#theme' => 'link',
'#text' => t('Download your Modernizr production build'),
'#path' => substr($link, 0, -1), // Truncate the last hyphen.
'#options' => array(
'attributes' => array(
'class' => array(
'button',
),
'target' => '_blank',
),
'html' => FALSE,
),
'#suffix' => '</div>',
);
// Create the download description render element.
$download_desc = array(
'#theme' => 'html_tag',
'#value' => t('The button links to a custom Modernizr build based on the tests listed above. <br/> Once you download the script, place it inside <b>!path</b> and !cc.', array(
'!path' => module_exists('libraries') ? libraries_get_path('modernizr') : 'sites/all/libraries/modernizr',
'!cc' => l(t('clear your cache'), 'admin/config/development/performance'),
)),
'#tag' => 'p',
);
// Print the Download link above and below the tests.
$elements['download_modernizr1']['link'] = $download_link;
$elements['download_modernizr2']['link'] = $download_link;
// Print the Download description above and below the tests.
$elements['download_modernizr1']['description'] = $download_desc;
$elements['download_modernizr2']['description'] = $download_desc;
// Load admin CSS
drupal_add_css(drupal_get_path('module', 'modernizr') . '/css/modernizr.admin.css');
return $elements;
}

View File

@ -0,0 +1,114 @@
<?php
/**
* @file
* Hooks provided by the Modernizr module
*/
/**
* @addtogroup hooks
* @{
*/
/**
* Registers a Modernizr dependency.
*
* This hook will not alter the production output of the module whatsoever.
* Its purpose is to tell the Drupal module which options are necessary if
* another Modernizr custom build is downloaded using the admin UI.
*
* Currently, you must visit the admin page for Modernizr and click the button
* in the admin UI to fetch the custom build. Future versions of the module will
* integrate with the node.js builder, allowing drush to generate a properly
* equipped Modernizr custom build.
*
* The module implements this function itself so feel free to look at
* modernizr_modernizr_info() for another example.
*
* @return
* An array of options that specify Modernizr custom build requirements.
*/
function hook_modernizr_info() {
$tests = array();
//
// The index of each entry MUST be the exact string needed in whatever
// version of modernizr.js you're using. These strings are not arbitrary.
// This Drupal module will always support the latest stable version of
// Modernizr and nothing else.
//
// Specify feature tests.
$tests[] = 'borderradius';
return $tests;
}
/**
* Registers a Modernizr.load() testObject.
*
* Modernizr.load() is actually a standalone library called yepnope.js
* which is included in Modernizr custom builder. This hook aims to
* offer 1:1 feature parity with yepnope.js - current version: 1.5
*
* Learn how all of these properties interact with Modernizr.load()
* on the yepnope website: http://yepnopejs.com/#testObject
*
* @return
* An array to be output as yepnope testObjects.
*/
function hook_modernizr_load() {
$load = array();
// Unlike hook_modernizr_info(), no array index is needed.
// You can add as many Modernizr.load() commands as you want
$load[] = array(
// The 'test' property determines which resources get downloaded.
// Your test can be *any* truthy JavaScript expression; you are NOT
// limited to Modernizr properties. You can combine tests like so:
//
// - Modernizr.borderradius && Modernizr.csstransforms3d
//
// This test requires the user's browser to support both border-radius
// and CSS 3D transforms.
//
// - Modernizr.mq('only screen and (min-width: 400px)') || !!respond
//
// This test requires the browser to support CSS3 media queries
// and have a window width of at least 400px or have access to
// the object provided by respond.js, a different JavaScript library
// which gives old browsers a minimal ability to eval min- and
// max-width media queries.
//
// Test the user's browser for border-radius support.
'test' => 'Modernizr.borderradius',
// If the test PASSES load these files. Example shows a hardcoded path.
'yep' => array('/css/radius.css'),
// If the test FAILS load these files. Example shows a Drupal path (don't
// forget opening slash, or it won't work except at your site root)
'nope' => array('/' . drupal_get_path('module', 'modernizr') . '/fake/path/to/radius.css'),
// These resources will always load regardless of the test results.
// 'load' and 'both' offer the exact same functionality.
'both' => array('/always/loaded.js'),
'load' => array('/always/loaded.js'),
// Each JavaScript callback should be enclosed inside an anonymous function.
// Take care to format correctly. You can provide an array of functions that
// should match the number of items in your yep or nope properties.
'callback' => array('function(){console.log("If you can see this, a Modernizr.load() individual callback was fired.")}'),
// The final 'complete' callback requires an anonymous JavaScript function.
// Take care to format correctly. Despite being inside an array, you should
// only add one function.
'complete' => array('function(){console.log("If you can see this, the Modernizr.load() complete callback was fired.")}'),
);
return $load;
}
/**
* @} End of "addtogroup hooks".
*/

View File

@ -0,0 +1,263 @@
<?php
/**
* @file
* An up-to-date list of Modernizr custom build args
* and the way in which they affect Modernizr. This
* file is the glue that makes the drush command for
* custom builds possible.
*/
function _modernizr_args_return($name) {
$modernizr_args = array(
// Tests
'applicationcache' => array(
'type' => 'tests',
'desc' => 'Browser cache layer that allows for offline usage of web applications.',
),
'audio' => array(
'type' => 'tests',
'desc' => 'Built-in audio support using <code>&lt;audio></code>.',
),
'borderradius' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for rounded corners.',
),
'boxshadow' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for drop-shadows around an element.',
),
'backgroundsize' => array(
'type' => 'tests',
'desc' => 'CSS property that allows a background image to resize based on its container.',
),
'borderimage' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for image-based borders around elements.',
),
'canvas' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows for dynamic, scriptable rendering of 2D shapes and bitmap images.',
),
'canvastext' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows for text effects within <code>&lt;canvas></code>.',
),
'cssanimations' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for keyframe-based animations.',
),
'csscolumns' => array(
'type' => 'tests',
'desc' => 'CSS property that allows elements to be formatted in columns.',
),
'cssgradients' => array(
'type' => 'tests',
'desc' => 'CSS property that creates vector-based background gradients.',
),
'cssreflections' => array(
'type' => 'tests',
'desc' => 'CSS property that creates a "reflection" below the element.',
),
'csstransforms' => array(
'type' => 'tests',
'desc' => 'CSS properties that allow elements to be moved or rotated in 2D space.',
),
'csstransforms3d' => array(
'type' => 'tests',
'desc' => 'CSS properties that allow elements to be moved or rotated in 3D space.',
),
'csstransitions' => array(
'type' => 'tests',
'desc' => 'CSS property that allow other CSS properties to smoothly tween between two values.',
),
'draganddrop' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows elements to be moved with the user\'s cursor.',
),
'flexbox' => array(
'type' => 'tests',
'desc' => 'CSS properties that allow for advanced, content-independent layouts.',
),
'flexboxlegacy' => array(
'type' => 'tests',
'desc' => 'An old version of the CSS properties that allow for advanced, content-independent layouts.',
),
'fontface' => array(
'type' => 'tests',
'desc' => 'CSS properties that allow use of web fonts.',
),
'generatedcontent' => array(
'type' => 'tests',
'desc' => 'CSS properties that allow CSS to generate presentational content.',
),
'geolocation' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows the browser to determine its physical location.',
),
'hashchange' => array(
'type' => 'tests',
'desc' => 'JavaScript API that provides an event listener for changes to <code>window.location.hash</code>.',
),
'history' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows <code>window.location</code> to be updated dynamically.',
),
'hsla' => array(
'type' => 'tests',
'desc' => 'CSS value that allows colors to be specified in terms of hue, saturation, lightness, and alpha.',
),
'indexeddb' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows access to a local database which supports indexing.',
),
'inlinesvg' => array(
'type' => 'tests',
'desc' => 'Browser support for inline SVG images.',
),
'input' => array(
'type' => 'tests',
'desc' => 'Browser support for new <code>&lt;input></code> attributes such as placeholder, autocomplete, required...',
),
'inputtypes' => array(
'type' => 'tests',
'desc' => 'Browser support for new <code>&lt;input></code> types such as color, date, number, tel...',
),
'localstorage' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows access to a simple key/value store that persists across sessions.',
),
'multiplebgs' => array(
'type' => 'tests',
'desc' => 'CSS value that allows multiple background images to be specified on a single element.',
),
'opacity' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for alpha transparency.',
),
'pointerevents' => array(
'type' => 'tests',
'desc' => 'JavaScript API for pointer events.',
),
'postmessage' => array(
'type' => 'tests',
'desc' => 'JavaScript API for cross-domain communication.',
),
'rgba' => array(
'type' => 'tests',
'desc' => 'CSS value that allows colors to be specified in terms of red, green, blue, and alpha.',
),
'sessionstorage' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows access to a simple key/value store. Cannot persist across sessions.',
),
'smil' => array(
'type' => 'tests',
'desc' => 'Synchronized Multimedia Integration Language.',
),
'svg' => array(
'type' => 'tests',
'desc' => 'Browser support for SVG images.',
),
'svgclippaths' => array(
'type' => 'tests',
'desc' => 'Browser support for non-rectangular element shapes.',
),
'textshadow' => array(
'type' => 'tests',
'desc' => 'CSS property that allows for drop-shadows behind text.',
),
'touchevents' => array(
'type' => 'tests',
'desc' => 'JavaScript API for touch events.',
),
'video' => array(
'type' => 'tests',
'desc' => 'Built-in video support using <code>&lt;video></code>.',
),
'webgl' => array(
'type' => 'tests',
'desc' => 'JavaScript API for WebGL, the 3D graphics layer.',
),
'websockets' => array(
'type' => 'tests',
'desc' => 'JavaScript API for asynchronous browser communication.',
),
'websqldatabase' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows access to a local database which supports a SQL-type language.',
),
'webworkers' => array(
'type' => 'tests',
'desc' => 'JavaScript API that allows execution of background processes.',
),
// Extensibility
'addtest' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that allows the user to define their own feature tests.',
),
'domprefixes' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that supplies DOM-style vendor prefixes.',
),
'hasevent' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that detects support for a given event.',
),
'prefixed' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that returns the prefixed or nonprefixed property name variant of its input.',
),
'prefixes' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that supplies CSS-style vendor prefixes.',
),
'teststyles' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that tests support for a specific CSS property.',
),
'testprop' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function investigates whether a given style property is recognized.',
),
'testallprops' => array(
'type' => 'extensibility',
'desc' => 'An internal Modernizr function that tests a list of DOM properties.',
),
// Extras
'load' => array(
'type' => 'extras',
'desc' => 'Provides yepnope.js, a conditional CSS/JS loader.',
),
'setclasses' => array(
'type' => 'extras',
'desc' => 'Allows Modernizr to inject CSS classes into <code>&lt;html&gt;</code>.',
),
'mq' => array(
'type' => 'extras',
'desc' => 'Allows Modernizr to evaluate CSS media queries.',
),
'printshiv' => array(
'type' => 'extras',
'desc' => 'Provides html5shiv (for browsers that do not support HTML5 tags). Support for printing.',
),
'shiv' => array(
'type' => 'extras',
'desc' => 'Provides html5shiv (for browsers that do not support HTML5 tags). No support for printing.',
),
// CSS Prefix
'cssclassprefix' => array(
'type' => 'extras',
'desc' => 'Allows the user to prefix injected Modernizr classes.',
),
);
if (isset($modernizr_args[$name])) {
return $modernizr_args[$name];
}
return FALSE;
}

View File

@ -0,0 +1,17 @@
name = Modernizr
description = Modernizr integration for Drupal. Extends the library by providing two APIs: (1) for test management (2) for exposing Modernizr.load() to Drupal
core = 7.x
package = Frontend
configure = admin/config/development/modernizr
files[] = modernizr.module
files[] = modernizr.install
files[] = modernizr.admin.inc
files[] = modernizr.args.inc
files[] = tests/modernizr.test
; Information added by Drupal.org packaging script on 2018-06-28
version = "7.x-3.11"
core = "7.x"
project = "modernizr"
datestamp = "1530180227"

View File

@ -0,0 +1,222 @@
<?php
/**
* @file
* Install file for Modernizr module.
*/
/**
* Implements hook_requirements().
*
* Changes its status based on ability to locate JS library.
* Changes its instructions based on Libraries API being enabled.
*/
function modernizr_requirements($phase) {
$requirements = array();
switch ($phase) {
case 'runtime':
/*
* Test for conditions
*/
// Fetch the version and force it to skip cache.
$version = modernizr_get_version(TRUE);
// Fetch the path to the JS lib.
$path = modernizr_get_path();
// Test if Libraries module is being used by comparing output of path functions
if (module_exists('libraries')) {
// If this is truthy, the Modernizr is using Libraries API as best we can tell.
$using_libraries = (strpos($path, libraries_get_path('modernizr')) !== FALSE);
}
else {
$using_libraries = FALSE;
}
/*
* Generate status message and severity
*/
// Modernizr / Libraries API installed and working correctly.
// Do the Drupal happy dance!
if ($path && $using_libraries) {
$description = FALSE;
$severity = REQUIREMENT_OK;
}
// Modernizr installed, but Libraries API not installed. Still acceptable, but nudge them.
elseif ($path && !$using_libraries) {
$description = t('Modernizr JS library is installed but you aren\'t using !libraries-api. You should use it.',
array(
'!libraries-api' => l(t('Libraries API'), 'http://drupal.org/project/libraries'),
)
);
$severity = REQUIREMENT_WARNING;
}
// Modernizr not installed, Libraries API is installed.
// Supply instructions recommending Libraries module.
elseif (!$path && module_exists('libraries')) {
$description = t('Modernizr JS library cannot be found. Download it from !modernizr-site, copy it into !path and rename it to modernizr.min.js.',
array(
'!modernizr-site' => l(t('modernizr.com'), 'http://modernizr.com/download/'),
// !path has a hardcoded default because the libraries_get_path() function might not return
// the correct path when conditions lead to this block of code being executed
'!path' => (libraries_get_path('modernizr')) ? libraries_get_path('modernizr') : 'sites/all/libraries/modernizr',
)
);
$severity = REQUIREMENT_ERROR;
}
// Modernizr not installed, Libraries API not installed.
// Supply generic instructions
else {
$description = t('Modernizr and Libraries API cannot be found. Download Modernizr from !modernizr-site, copy it into !path and rename it to modernizr.min.js. You should also use the !libraries-api by installing from drupal.org.',
array(
'!modernizr-site' => l(t('modernizr.com'), 'http://modernizr.com/download/'),
'!path' => 'sites/all/libraries/modernizr',
'!libraries-api' => l(t('Libraries API'), 'http://drupal.org/project/libraries'),
)
);
$severity = REQUIREMENT_ERROR;
}
/**
* We need a secondary set of requirements in case all modernizr tests
* requested are not added to the current modernizr build. This will only
* run if modernizr is available.
*/
if ($path) {
$missing_tests = _modernizr_info_missing_tests();
if (empty($missing_tests)) {
// There are no missing tests! We are awesome!
$tests_value = t('All required tests are present in current Modernizr build.');
$tests_description = FALSE;
$tests_severity = REQUIREMENT_OK;
}
else {
// Pull tests that are currently set.
$current_tests = _modernizr_current_build();
// If the custom build hasn't been created yet, we should report that
// instead of saying that they're missing altogether. The development
// copy has all the tests, so none are missing. However, dev does NOT
// have Modernizr.load(), so it still registers as a full-blown error
// by default.
if (is_null($current_tests)) {
$tests_value = t('You haven\'t created a custom build yet.');
$tests_description = t('Modernizr only works with a custom build. Visit the !modernizr-settings to create one.', array('!modernizr-settings' => l(t('Modernizr settings page'), 'admin/config/development/modernizr')));
$tests_severity = variable_get('modernizr_quiet', MODERNIZR_QUIET_DEFAULT) ? REQUIREMENT_WARNING : REQUIREMENT_ERROR;
}
else {
// Custom build exists, and tests are missing, we need to fix that.
$tests_value = t('Tests are missing in current Modernizr build.');
$tests_description = t('Certain tests requested by currently enabled modules and themes are not within the current Modernizr build. Go to the !link to download a new version of Modernizr. The tests that are missing are: ', array('!link' => l(t('Modernizr settings page'), 'admin/config/development/modernizr'))) . '<code>' . implode('</code>, <code>', array_keys($missing_tests)) . '</code>';
$tests_severity = variable_get('modernizr_quiet', MODERNIZR_QUIET_DEFAULT) ? REQUIREMENT_WARNING : REQUIREMENT_ERROR;
}
}
/**
* Declare requirement to Drupal
*/
$requirements[] = array(
'title' => t('Modernizr Tests'),
'value' => $tests_value,
'description' => $tests_description,
'severity' => $tests_severity,
);
}
/*
* Declare requirement to Drupal
*/
$requirements[] = array(
'title' => t('Modernizr'),
'value' => $version ? $version : t('Not installed'),
'description' => $description,
'severity' => $severity,
);
break;
}
return $requirements;
}
/**
* Set module weight.
*/
function modernizr_set_module_weight() {
db_update('system')
->fields(array('weight' => 10))
->condition('name', 'modernizr', '=')
->execute();
}
/**
* Implements hook_install().
*/
function modernizr_install() {
modernizr_set_module_weight();
}
/**
* Implements hook_uninstall().
*/
function modernizr_uninstall() {
// Delete drupal_add_js() options.
variable_del('modernizr_load');
variable_del('modernizr_scope');
variable_del('modernizr_type');
// Delete Drupal admin UI options.
variable_del('modernizr_quiet');
// Delete custom build options.
variable_del('modernizr_cb_printshiv');
variable_del('modernizr_cb_load');
}
/**
* Delete the deprecated 'modernizr_serverside' variable.
*/
function modernizr_update_7300() {
variable_del('modernizr_serverside');
return t("Deleted 'modernizr_serverside' variable");
}
/**
* Revert the introduction of 'defer' as the default method of including script.
*/
function modernizr_update_7301() {
// Setting `defer` as default was a bad idea, because:
// 1. The deferred script almost always gets executed after any inlined
// Modernizr.load() commands.
//
// @see https://www.drupal.org/node/2252899#comment-9228009
//
// 2. Setting `defer` by default is bad for backwards-compatibility.
//
// @see https://www.drupal.org/node/2252899#comment-9383221
if (variable_get('modernizr_type', MODERNIZR_TYPE_DEFAULT) == 'defer') {
variable_set('modernizr_type', MODERNIZR_TYPE_DEFAULT);
}
}
/**
* Increase module weight to override other modules library definitions.
*/
function modernizr_update_7302() {
modernizr_set_module_weight();
return t('Increased Modernizr module weight.');
}
/**
* Automatically enable yepnope.js for backwards compatibility.
*/
function modernizr_update_7303() {
variable_set('modernizr_cb_load', 1);
return t('Enabled yepnope.js for backwards compatibility.');
}

View File

@ -0,0 +1,838 @@
<?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
);
}
// If there are yepnope commands being requested, but the module does not
// have yepnope enabled, warn the user in the console.
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));
}
// Skip the ['tests'] variable because it is reserved for selecting
// specific tests that Modernizr must include.
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++;
}
// No test is defined, add the resource(s) to the loader unconditionally.
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;
}

View File

@ -0,0 +1,57 @@
<?php
/**
* @file
* Tests for Modernizr module.
*/
/**
* Tests basic Modernizr API functions.
*/
class ModernizrUnitTestCase extends DrupalUnitTestCase {
/**
* Displays a description in testing UI.
*/
public static function getInfo() {
return array(
'name' => 'Modernizr module unit tests',
'description' => 'Tests basic api functions provided by Modernizr module.',
'group' => 'Modernizr',
);
}
/**
* Basic setup for Modernizr module tests.
*/
function setUp() {
drupal_load('module', 'modernizr');
parent::setUp();
}
/**
* Tests that Modernizr is implementing hook_modernizr_info() correctly.
*/
function testModernizrInfo() {
global $conf;
// By default there are no tests
$tests = modernizr_modernizr_info();
if (is_array($tests)) {
$this->assertEqual(count($tests), 0, 'No tests by default');
}
else {
$this->fail('modernizr_modernizr_info returns an array');
}
// Now we require the printshiv test.
$conf['modernizr_cb_printshiv'] = TRUE;
$tests = modernizr_modernizr_info();
if (is_array($tests)) {
$test = array_shift($tests);
$this->assertEqual($test, 'printshiv', 'printshiv test enabled');
}
else {
$this->fail('modernizr_modernizr_info returns an array');
}
}
}