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
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 Methods
JavaScriptResource Interface Methods
CssResource Interface Methods
ResourceManager Interface
JSON Configuration File
JavaScript JSON
CSS JSON
File System and Config File Naming
Wrapper Script
These 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