dev-master
9999999-dev https://github.com/AliceWonderMiscreations/NotReallyPsrResourceManagerA Proposal for a web application JS/CSS resouce manager
MIT
The Requires
- php ~7.1.0 || ~7.2.0
The Development Requires
by Alice Wonder
Wallogit.com
2017 © Pedro Peláez
A Proposal for a web application JS/CSS resouce manager
This is a set of interfaces that PHP libraries can use to provide sane management of third party JavaScript and CSS resources uses by the web applications., (*1)
The current namespace \AWonderPHP\NotReallyPsrResourceManager sucks and will
change. It was never intended as permanent. I was hoping a standards body would
want to take this idea and create some standard interfaces with fancy lingo
that includes RFC 2119., (*2)
While not strictly required, it is highly recommended that classes that
implement these interfaces extend the abstract classes within the
\AwonderPHP\FileResource
namespace., (*3)
That allows the resulting objects to be served by any class that understands
how to serve a FileResource object., (*4)
It is also intended that the JavaScriptResource and CssResource objects be generated from JSON configuration files as described in this document., (*5)
FileResource MethodsJavaScriptResource Interface MethodsCssResource Interface MethodsResourceManager InterfaceJSON Configuration FileJavaScript JSONCSS JSONFile System and Config File NamingWrapper ScriptThese methods are specified in both the JavaScriptResource and CssResource
interfaces and are identical to the methods of the same name in the abstract
\AwonderPHP\FileResource\FileResource class:, (*6)
public function getMimeType()
Returns the $mime property., (*7)
public function getChecksum()
Returns the $checksum property., (*8)
public function getCrossOrigin()
Returns the $crossorigin property., (*9)
public function getFilePath()
Returns the $filepath property., (*10)
public function validateFile()
If the $checksum property is set and the $filepath property is set
and the file exists, returns true if the file matches the checksum and
false if it does not., (*11)
public function getSrcAttribute($prefix = null)
Builds the contents of the src or href attribute needed to embed the
resource in a web page. Note that this will return null if the $urlscheme
property is http and the file does not have a $checksum property that
uses an algorithm in the $validIntegrityAlgo property. The optional
parameter $prefix is a file system path to put in front of the $urlpath
property, useful for web applications using a wrapper to serve the file., (*12)
public function getIntegrityAttribute()
Builds the contents of an integrity attribute, if the $checksum property
uses a suitable algorithm., (*13)
public function getTimestamp()
If the $lastmode property is not null, returns a UNIX time stamp (seconds
from UNIX epoch)., (*14)
These methods are in the JavaScriptResource interface but are not defined in
the previously mentioned FileResource abstract class., (*15)
getTypeAttribute()
What goes into the type attribute of a <script> node. Usually the MIME
type but not always., (*16)
getAsyncAttribute()
Whether or not the Boolean async attribute should be present., (*17)
getDeferAttribute();
Whether or not the Boolean defer attribute should be present., (*18)
getNoModuleAttribute()
Whether or not the Boolean nomodule attribute should be present., (*19)
generateScriptDomNode($dom, $nonce = null)
Creates a \DOMNode <script> node, with an optional nonce., (*20)
generateScriptString(bool $xml = false, $nonce = null)
Creates a string, either HTML or XHTML, for the script node with an optional
nonce. If the $xml parameter is true, a string that is XML compliant
should be returned (every attribute is a key="value" pair, Boolean
attributes are usually just key="key" but it does not really matter. Script
node is self-closing). When the $xml parameters is false, the default, an
HTML compliant string is generated (boolean attributes may just be key
and are not required to have an ="value" and a self-closing script tags are
not recognized as closed, so a closing </script> is required)., (*21)
Both the generateScriptDomNode() and generateScriptString() methods should
call the getSrcAttribute() method, so the constructor of an implementing
class should have a property for the $prefix that is null by default but
can be set by the constructor., (*22)
getTypeAttribute()
What goes into the type attribute of a CSS <link> node. This should
ALWAYS return text/css, (*23)
getMediaAttribute()
Returns what goes into the media attribute of a CSS <link> node. This is
rarely used, but it is very powerful and should be used more often IMHO as it
can reduce the bandwidth the client needs to have to successfully use a web
application., (*24)
getHreflangAttribute()
Returns what goes into a hreflang attribute. When not null, it MUST be
a BCP47 string., (*25)
getReferrerPolicyAttribute()
Returns what goes into a referrerpolicy attribute of a CSS <link> node. I
suspect it will not be used much, but it is there., (*26)
getRelAttribute()
The contents of the rel attribute, should return stylesheet., (*27)
This is the interface that defines how web applications will interact get the
JavaScriptResource and CssResource objects that they need., (*28)
It describes two public methods:, (*29)
getJavaScript(string $vendor, string $product, string $name, $version, $variant = null);, (*30)
getCSS(string $vendor, string $product, string $name, $version, $variant = null);, (*31)
The web application calls those methods which will either return null if the
implementing class can not create the object, or it returns eith a
JavaScriptResource or CssResource implementing object, depending upon which
of the methods were called., (*32)
$vendor String:
Lower case vendor string for who packaged the JavaScript or CSS, similar to
the first level namespace in PSR-4 PHP classes but lower case. In Composer
terms, it would be the top level directory within the Composer created
vendor directory of your web application., (*33)
$product String:
Lower case product string for the package the JavaScript or CSS is part of,
similar to the second level namespace in PSR-4 PHP classes but lower case. In
Composer terms, it would be the directory within the previously mentioned
directory., (*34)
$name String:
The name of the JavaScript or CSS sans version and other info, e.g. jquery
or jquery-ui or normalize., (*35)
$version String or Integer:
The version needed, e.g. 3.3.1 to specifically ask for jQuery 3.3.1 or
3.3 to specifically ask for latest in 3.3 branch or simply 3 to ask
for the latest in 3 branch., (*36)
$variant String or Null:
The variant of the JavaScript needed, e.g. min for minified or slim or
slim.min., (*37)
With that information, the ResourceManager implementing class would be able
to find the JSON file describing the object and load it into an object., (*38)
The constructor for an implementing class should define the Base directory
directory resources are installed into so the methods can find the needed
configuration files and also the $prefix to use with the getSrcAttribute()
method., (*39)
$base = "/whatever/path";
$RM = new \namespace\whatever\ImplementingClass($base);
$jsObj = $RM->getJavaScript('flossjs', 'jquery', 'jquery', 3, "min");
Then from $jsObj the web application can create the <script> node needed., (*40)
The ResourceManager will hunt for a JSON configuration file that matches the resource the web application requests and then create the object to return from the JSON file. That needs a standard JSON file format., (*41)
name String, required:jquery.homepage String, not strictly required:version String, required:license Array, required:Those fields are not utilized by the classes but are metadata that is useful to a system administrator. Other fields common to both JS and CSS:, (*42)
mime String, required:checksum String, recommended:algo:checksum described in the FileResource abstract class.filepath String, optional:lastmod String, recommended:strtotime() to create a UNIX time stamp
indicating when the file was last modified. For many projects, this is
specified in a comment header of the file itself, and in those cases, that
string should be used.srcurl String, required:src or href attribute. Must be parseable by the
parse_url function and internationalized domains should be in punycode.minified Boolean, optional:A sample of what a JavaScript JSON might look like:, (*43)
{
"name": "jquery",
"homepage": "https://jquery.com/",
"version": "3.3.1",
"license": [
{
"name": "MIT",
"url": "https://jquery.org/license/"
}
],
"mime": "application/javascript",
"checksum": "sha256:160a426ff2894252cd7cebbdd6d6b7da8fcd319c65b70468f10b6690c45d02ef",
"filepath": "flossjs/jquery/js/jquery-3.3.1.min.js",
"lastmod": "2018-01-20T17:24Z",
"minified": true,
"srcurl": "/js/jquery-3.3.1.min.js"
}
JavaScript Specific Fields:, (*44)
async Boolean, optional:true.defer Boolean, optional:true.nomodule Boolean, optional:true.type?? Needs Exploration:type attribute is set to the MIME type, but it may be
necessary to set it to modular for ES6 modular feature, I still need to
learn about that.A sample of what a CSS JSON might look like needs to be written., (*45)
CSS Specific Fields:, (*46)
media Array, optional:all when not specified)hreflang String, optional:referrerpolicy String, optional:no-referrer, no-referrer-when-downgrade,
origin, origin-when-cross-origin, unsafe-url -- browsers assume
no-referrer-when-downgrade which is almost always the best policy for
CSS style sheets. It is my opinion that unsafe-url should never be
used as it can leak information. It only has meaning when the remote server
does not use TLS but your web application uses TLS and that scenario should
be blocked by browsers anyway.All scripts should be installed with a hierarchy of
$base/VendorName/ProductName where VendorName and ProductName are lower
case, as is Composer convention for PHP libraries., (*47)
In the case of Composer install of JS/CSS libraries, the Composer vendor
directory would be the $base directory., (*48)
Within the ProductName directory, an etc directory MUST exist that has
the JSON configuration files, and it is RECOMMENDED that the actual
JavaScript files reside in a js directory and CSS files reside in a css
directory., (*49)
An example of what this would look like is at AliceWonderMiscreations/CommonJS, (*50)
Default configuration files would be named using:, (*51)
ScriptName-Version-Variant.json.dist
Where ScriptName is the name of the script (e.g. jquery), Version is the
version of the script (e.g. 3.3.1), and if present, Variant would be the
script variant (e.g. min or slim or slim.min)., (*52)
The default configuration should have the srcurl point to a local URL, e.g., (*53)
"srcurl": "/js/jquery-3.3.1.min.js",
When a system administrator wants to customize what is in the configuration,
they simply copy the file so that it no longer ends in .dist and then they
can modify it (e.g. to set srcurl to a CDN)., (*54)
The ResourceManager MUST give priority to the configuration file without
the .dist if it is found., (*55)
With the major.minor.point versioning scheme, a configuration file should
exist for both major.minor and major that are identical to the default
configuration file for the most recent major.minor.point that match., (*56)
Web Applications that implement this MUST be able to handle requests to the
default /js/ and /css/ locations., (*57)
This can be accomplished by a wrapper script. An abstract class that extends
the FileWrapper class
to work for this has been written, that abstract class is part of the
AWonderPHP\FileResource
namespace., (*58)
An interface exists in this namespace that can be used to define a class that
extends the class that serves FileResource objects described above., (*59)
EOF, (*60)
A Proposal for a web application JS/CSS resouce manager
MIT