Skip to content
Snippets Groups Projects
Commit 11219be0 authored by 🙄 ✻'s avatar 🙄 ✻
Browse files

https://github.com/elmsln/HAXcms/issues/343 D6Webcomponents normalization

parent 67906bc3
Branches
Tags 6.x-3.1
No related merge requests found
## Usage
This should give you the dependencies you need to get going.
1. Enable the Web components module and any dependencies it requires.
2. The default is to serve JS assets up from a CDN. Should you need to change this
# Front end Developers
You may build Web components from source if needed. We default to use CDNs which will effectively point to
this directory or some mutation of it -- https://github.com/elmsln/HAXcms/tree/master/build
If you want to build everything from source, your welcome to use yarn / npm to do so though our
build routine effectively will end in the same net result. If you want to do custom build routines
such as rollup or webpack and not use our prebuilt copies / split build approaches, then your welcome
to check the box related to not loading front end assets in the settings page in order to tailor
the build to your specific needs.
## Getting dependencies
You need polymer cli (not polymer but the CLI library) in order to interface with web components in grav. Get polymer cli installed prior to usage of this (and (yarn)[https://yarnpkg.com/lang/en/docs/install/#mac-stable] / an npm client of some kind)
You need polymer cli (not polymer but the CLI library) in order to interface with web components in your site. Get polymer cli installed prior to usage of this (and (yarn)[https://yarnpkg.com/lang/en/docs/install/#mac-stable] / an npm client of some kind)
```bash
$ yarn global add polymer-cli
# or...
$ npm install -g polymer-cli
```
Perform this on your computer locally, this doesn't have to be installed on your server.
## Usage
Find the `CopyThisStuff` directory in `/sites/all/modues/webcomponents` and copy the files in there over to `/sites/all/libraries/webcomponents`.
- Find `CopyThisStuff` directory in `/sites/all/modules/webcomponents`.
- create a `/sites/all/libraries/webcomponents` directory
- copy the files from `CopyThisStuff` into `/sites/all/libraries/webcomponents`
Then run the following (from the directory you copied it over to) in order to get dependencies:
```bash
$ yarn install
# or...
$ npm install
```
Now run `polymer build` and you'll have files in `build/` which contain everything you'll need to get wired up to web components in your grav site. Modifying build.js or package.json can be used in order to get new elements and have them be implemented.
Now run `polymer build` and you'll have files in `build/` which contain everything you'll need to get wired up to web components in your site. Modifying build.js or package.json can be used in order to get new elements and have them be implemented.
### Shouldn't I put web components in my theme?
We don't think so. While it may seem counter intuitive, the theme layer should be effectively implementing what Grav is saying is available. If you think of standard HTML tags are being part of this (p, div, a, etc) then it makes a bit more sense. You don't want functional HTML components to ONLY be supplied if your theme is there, you want your theme to implement and leverage the components.
We don't think so. While it may seem counter intuitive, the theme layer should be effectively implementing what the site is saying is available. If you think of standard HTML tags are being part of this (p, div, a, etc) then it makes a bit more sense. You don't want functional HTML components to ONLY be supplied if your theme is there, you want your theme to implement and leverage the components.
## New to web components?
We built our own tooling to take the guess work out of creating, publishing and testing web components for HAX and other projects. We highly recommend you use this tooling though it's not required:
We built our own tooling to take the guess work out of creating, publishing and testing web components. We highly recommend you use this tooling though it's not required:
- https://open-wc.org - great, simple tooling and open community resource
- https://github.com/elmsln/wcfactory - Build your own web component library
- https://github.com/elmsln/lrnwebcomponents - Our invoking of this tooling to see what a filled out repo looks like
......
......@@ -6,50 +6,64 @@ class WebComponentsService {
/**
* This applies all pieces of a standard build appended to the header
*/
public function applyWebcomponents($directory = '/') {
public function applyWebcomponents($directory = '/', $files = array('build.js')) {
return
$this->getPolyfill($directory) .
$this->getBabel($directory) .
$this->getBuild($directory);
$this->getBuild($directory, $files);
}
/**
* Return the polyfill standard method of application
* Front end logic for ES5-AMD, ES6-AMD, ES6 version to deliver
*/
public function getPolyfill($directory = '/') {
return '<!-- cross platform polyfill -->
<script>if (!window.customElements) { document.write("<!--") }</script>
<script defer="defer" type="text/javascript" src="' . $directory . 'build/es6/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
<!--! do not remove -->
<script defer="defer" src="' . $directory . 'build/es6/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script defer="defer" src="' . $directory . 'build/es6/node_modules/web-animations-js/web-animations-next-lite.min.js"></script>
<!-- / cross platform polyfill -->';
}
/**
* Get babel helpers to ensure compiled versions have appropriate functions
*/
public function getBabel($directory = '/') {
return '<!-- babel -->
<script src="' . $directory . 'babel/babel-top.js"></script>
<script src="' . $directory . 'babel/babel-bottom.js"></script>
<!-- / babel -->';
}
/**
* Front end logic for ES5 or ES6 version to deliver
*/
public function getBuild($directory = '/') {
return '<!-- web component build -->
<script nomodule>window.nomodule = true;</script>
<script>
function __supportsImports() { try { new Function(\'import("")\'); return true; } catch (err) { return false; } }
// lack of es modules or dynamic imports requires amd-es5 bundle
if (window.nomodule || !__supportsImports()) {
define(["' . $directory . 'build/es5-amd/build.js"], function () { "use strict" });
document.write("<!--")
public function getBuild($directory = '/', $files = array('build.js')) {
$es5 = array();
$es6Amd = array();
$es6 = array();
foreach ($files as $file) {
array_push($es5, 'cdn + "build/es5-amd/' . $file . '"');
array_push($es6Amd, 'cdn + "build/es6-amd/' . $file . '"');
array_push($es6, 'import "' . $directory . 'build/es6/' . $file . '";');
}
return '<script>var cdn="' . $directory . '";var old=false;
try { new Function(\'import("")\'); } catch (err) {
if (typeof Symbol == "undefined") { // IE 11, at least try to serve the components
if (!(window.ActiveXObject) && "ActiveXObject" in window) {
"use strict"; (function () { function a(a, b, c) { var d = a; if (d.state = b, d.stateData = c, 0 < d.onNextStateChange.length) { var e = d.onNextStateChange.slice(); d.onNextStateChange.length = 0; for (var f, g = 0, h = e; g < h.length; g++)f = h[g], f() } return d } function b(b) { function d() { try { document.head.removeChild(f) } catch (a) { } } var e = a(b, "Loading", void 0), f = document.createElement("script"); return f.src = b.url, f.onload = function () { var a, b, f; void 0 === r ? (b = [], f = void 0) : (a = r(), b = a[0], f = a[1]), c(e, b, f), d() }, f.onerror = function () { g(b, new TypeError("Failed to fetch " + b.url)), d() }, document.head.appendChild(f), e } function c(b, c, e) { var f = d(b, c), g = f[0], h = f[1]; return a(b, "WaitingForTurn", { args: g, deps: h, moduleBody: e }) } function d(a, c) { for (var e, f = [], g = [], i = 0, j = c; i < j.length; i++) { if (e = j[i], "exports" === e) { f.push(a.exports); continue } if ("require" === e) { f.push(function (b, c, e) { var f = d(a, b), g = f[0], i = f[1]; h(i, function () { c && c.apply(null, g) }, e) }); continue } if ("meta" === e) { f.push({ url: !0 === a.isTopLevel ? a.url.substring(0, a.url.lastIndexOf("#")) : a.url }); continue } var l = k(n(a.urlBase, e)); f.push(l.exports), g.push(l), "Initialized" === l.state && b(l) } return [f, g] } function e(b) { var c = a(b, "WaitingOnDeps", b.stateData); return h(b.stateData.deps, function () { return f(c) }, function (a) { return g(c, a) }), c } function f(b) { var c = b.stateData; if (null != c.moduleBody) try { c.moduleBody.apply(null, c.args) } catch (a) { return g(b, a) } return a(b, "Executed", void 0) } function g(b, c) { return !0 === b.isTopLevel && setTimeout(function () { throw c }), a(b, "Failed", c) } function h(a, b, c) { var d = a.shift(); return void 0 === d ? void (b && b()) : "WaitingOnDeps" === d.state ? (!1, void h(a, b, c)) : void i(d, function () { h(a, b, c) }, c) } function i(a, b, c) { switch (a.state) { case "WaitingForTurn": return e(a), void i(a, b, c); case "Failed": return void (c && c(a.stateData)); case "Executed": return void b(); case "Loading": case "WaitingOnDeps": return void a.onNextStateChange.push(function () { return i(a, b, c) }); case "Initialized": throw new Error("All dependencies should be loading already before pressureDependencyToExecute is called."); default: throw new Error("Impossible module state: " + a.state); } } function j(a, b) { switch (a.state) { case "Executed": case "Failed": return void b(); default: a.onNextStateChange.push(function () { return j(a, b) }); } } function k(a) { var b = q[a]; return void 0 === b && (b = q[a] = { url: a, urlBase: m(a), exports: Object.create(null), state: "Initialized", stateData: void 0, isTopLevel: !1, onNextStateChange: [] }), b } function l(a) { return v.href = a, v.href } function m(a) { return a = a.split("?")[0], a = a.split("#")[0], a.substring(0, a.lastIndexOf("/") + 1) } function n(a, b) { return -1 === b.indexOf("://") ? l("/" === b[0] ? b : a + b) : b } function o() { return document.baseURI || (document.querySelector("base") || window.location).href } function p() { var b = document.currentScript; if (!b) return u; if (window.HTMLImports) { var c = window.HTMLImports.importForElement(b); return c ? c.href : u } var d = b.ownerDocument.createElement("a"); return d.href = "", d.href } if (!window.define) { var q = Object.create(null), r = void 0, s = 0, t = void 0, u = o(); window.define = function (a, b) { var d = !1; r = function () { return d = !0, r = void 0, [a, b] }; var f = p(); setTimeout(function () { if (!1 == d) { r = void 0; var g = f + "#" + s++, h = k(g); h.isTopLevel = !0; var i = c(h, a, b); void 0 === t ? e(i) : j(k(t), function () { e(i) }), t = g } }, 0) }, window.define._reset = function () { for (var a in q) delete q[a]; r = void 0, s = 0, t = void 0, u = o() }; var v = document.createElement("a") } })();
var defs = [
cdn + "build/es5-amd/node_modules/web-animations-js/web-animations-next-lite.min.js",
cdn + "build/es5-amd/node_modules/promise-polyfill/dist/polyfill.min.js",
cdn + "build/es5-amd/node_modules/fetch-ie8/fetch.js",
cdn + "babel/babel-top.js"
];
defs.push(' . implode(',', $es5) . ');
define(defs, function () { "use strict" });
define([cdn + "build/es5-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"], function () { "use strict" });
}
}
else {
"use strict"; (function () { function a(a, b, c) { var d = a; if (d.state = b, d.stateData = c, 0 < d.onNextStateChange.length) { var e = d.onNextStateChange.slice(); d.onNextStateChange.length = 0; for (var f, g = 0, h = e; g < h.length; g++)f = h[g], f() } return d } function b(b) { function d() { try { document.head.removeChild(f) } catch (a) { } } var e = a(b, "Loading", void 0), f = document.createElement("script"); return f.src = b.url, f.onload = function () { var a, b, f; void 0 === r ? (b = [], f = void 0) : (a = r(), b = a[0], f = a[1]), c(e, b, f), d() }, f.onerror = function () { g(b, new TypeError("Failed to fetch " + b.url)), d() }, document.head.appendChild(f), e } function c(b, c, e) { var f = d(b, c), g = f[0], h = f[1]; return a(b, "WaitingForTurn", { args: g, deps: h, moduleBody: e }) } function d(a, c) { for (var e, f = [], g = [], i = 0, j = c; i < j.length; i++) { if (e = j[i], "exports" === e) { f.push(a.exports); continue } if ("require" === e) { f.push(function (b, c, e) { var f = d(a, b), g = f[0], i = f[1]; h(i, function () { c && c.apply(null, g) }, e) }); continue } if ("meta" === e) { f.push({ url: !0 === a.isTopLevel ? a.url.substring(0, a.url.lastIndexOf("#")) : a.url }); continue } var l = k(n(a.urlBase, e)); f.push(l.exports), g.push(l), "Initialized" === l.state && b(l) } return [f, g] } function e(b) { var c = a(b, "WaitingOnDeps", b.stateData); return h(b.stateData.deps, function () { return f(c) }, function (a) { return g(c, a) }), c } function f(b) { var c = b.stateData; if (null != c.moduleBody) try { c.moduleBody.apply(null, c.args) } catch (a) { return g(b, a) } return a(b, "Executed", void 0) } function g(b, c) { return !0 === b.isTopLevel && setTimeout(function () { throw c }), a(b, "Failed", c) } function h(a, b, c) { var d = a.shift(); return void 0 === d ? void (b && b()) : "WaitingOnDeps" === d.state ? (!1, void h(a, b, c)) : void i(d, function () { h(a, b, c) }, c) } function i(a, b, c) { switch (a.state) { case "WaitingForTurn": return e(a), void i(a, b, c); case "Failed": return void (c && c(a.stateData)); case "Executed": return void b(); case "Loading": case "WaitingOnDeps": return void a.onNextStateChange.push(function () { return i(a, b, c) }); case "Initialized": throw new Error("All dependencies should be loading already before pressureDependencyToExecute is called."); default: throw new Error("Impossible module state: " + a.state); } } function j(a, b) { switch (a.state) { case "Executed": case "Failed": return void b(); default: a.onNextStateChange.push(function () { return j(a, b) }); } } function k(a) { var b = q[a]; return void 0 === b && (b = q[a] = { url: a, urlBase: m(a), exports: Object.create(null), state: "Initialized", stateData: void 0, isTopLevel: !1, onNextStateChange: [] }), b } function l(a) { return v.href = a, v.href } function m(a) { return a = a.split("?")[0], a = a.split("#")[0], a.substring(0, a.lastIndexOf("/") + 1) } function n(a, b) { return -1 === b.indexOf("://") ? l("/" === b[0] ? b : a + b) : b } function o() { return document.baseURI || (document.querySelector("base") || window.location).href } function p() { var b = document.currentScript; if (!b) return u; if (window.HTMLImports) { var c = window.HTMLImports.importForElement(b); return c ? c.href : u } var d = b.ownerDocument.createElement("a"); return d.href = "", d.href } if (!window.define) { var q = Object.create(null), r = void 0, s = 0, t = void 0, u = o(); window.define = function (a, b) { var d = !1; r = function () { return d = !0, r = void 0, [a, b] }; var f = p(); setTimeout(function () { if (!1 == d) { r = void 0; var g = f + "#" + s++, h = k(g); h.isTopLevel = !0; var i = c(h, a, b); void 0 === t ? e(i) : j(k(t), function () { e(i) }), t = g } }, 0) }, window.define._reset = function () { for (var a in q) delete q[a]; r = void 0, s = 0, t = void 0, u = o() }; var v = document.createElement("a") } })();
var defs = [
cdn + "build/es6-amd/node_modules/web-animations-js/web-animations-next-lite.min.js",
cdn + "babel/babel-top.js"
];
if (window.customElements) { // certain FF / Safari versions
defs.push(cdn + "build/es6-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js");
}
else {
defs.push(cdn + "build/es6-amd/node_modules/promise-polyfill/dist/polyfill.min.js");
defs.push(cdn + "build/es6-amd/node_modules/fetch-ie8/fetch.js");
defs.push(cdn + "build/es6-amd/node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js");
}
defs.push(' . implode(',', $es6Amd) . ');
define(defs, function () { "use strict" });
}
</script>
<script type="module" defer="defer" src="' . $directory . 'build/es6/build.js"></script>
<!--! do not remove -->
<!-- / web component build -->';
old=true;
}
</script>
<script>if(old)document.write(\'<!--\');</script>
<script async defer type="module">
' . implode("\n", $es6) . '
</script>
<script async src="' . $directory . 'build/es6/node_modules/web-animations-js/web-animations-next-lite.min.js">
//<!--! do not remove -->
</script>';
}
}
\ No newline at end of file
......@@ -101,12 +101,25 @@ function webcomponents_menu() {
*/
function webcomponents_admin_settings() {
$form = array();
$form['webcomponents_project_location'] = array(
$form['webcomponents_project_location'] = [
'#type' => 'select',
'#title' => t('Webcomponents Location'),
'#default_value' => variable_get('webcomponents_project_location', 'https://webcomponents.psu.edu/cdn/'),
'#options' => array(
'sites/all/libraries/webcomponents/' => 'Local libraries folder (sites/all/libraries/webcomponents/)',
'https://webcomponents.psu.edu/cdn/' => 'Penn State CDN',
'https://cdn.waxam.io/' => 'Waxam CDN',
'other' => t('Other'),
),
'#description' => t("Use this to point to CDNs or if you've installed your web components some place else. Start without a slash and end with a slash."),
];
$form['webcomponents_project_location_other'] = [
'#type' => 'textfield',
'#title' => t('CDN location'),
'#default_value' => variable_get('webcomponents_project_location', 'sites/all/libraries/webcomponents/'),
'#description' => t("Base path needs to start without a slach and end with a slash. This supports CDNs as well."),
);
'#title' => t('Other Location'),
'#default_value' => variable_get('webcomponents_project_location_other', ''),
'#maxlength' => 1000,
'#description' => t("Only use this if you need to use a source other than the above supported options."),
];
return system_settings_form($form);
}
......@@ -114,16 +127,21 @@ function webcomponents_admin_settings() {
* Implements hook_init().
*/
function webcomponents_init() {
$location = variable_get('webcomponents_project_location', 'sites/all/libraries/webcomponents/');
$location = variable_get('webcomponents_project_location', 'https://webcomponents.psu.edu/cdn/');
if ($location == 'other') {
$location = variable_get('webcomponents_project_location_other', '');
}
// append base_path if this site has a url to start it
if (strpos($location, 'http') === FALSE) {
$location = base_path() . $location;
}
// load webcomponentsjs polyfill library if it exists
$files = array('build.js');
drupal_alter('webcomponents_build_file_location', $files);
$wc = new WebComponentsService();
$element = array(
'#type' => 'markup',
'#markup' => $wc->applyWebcomponents($location),
'#markup' => $wc->applyWebcomponents($location, $files),
);
drupal_add_html_head($element, 'webcomponents');
}
......@@ -176,7 +194,7 @@ function _webcomponents_render_component($component) {
$vars['properties']['class'] .= ' ' . WEBCOMPONENTS_CLASS_IDENTIFIER;
}
// allow other projects to add onto and modify the webcomponent before it renders
// useful for tag wrapping for systems like HAX
// useful for tag wrapping for systems
drupal_alter('webcomponent_render', $vars, $component);
$output = theme('webcomponent', $vars);
return $output;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment