Skip to content

Commit cbede78

Browse files
author
Andrew Welch
committed
Intial manifest work
1 parent 8734562 commit cbede78

File tree

2 files changed

+132
-207
lines changed

2 files changed

+132
-207
lines changed

src/helpers/Manifest.php

Lines changed: 106 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212
namespace nystudio107\transcoder\helpers;
1313

14+
use nystudio107\transcoder\assetbundles\transcoder\TranscoderAsset;
15+
1416
use Craft;
1517
use craft\helpers\Json as JsonHelper;
1618
use craft\helpers\UrlHelper;
1719

1820
use yii\base\Exception;
21+
use yii\base\InvalidConfigException;
1922
use yii\caching\TagDependency;
2023
use yii\web\NotFoundHttpException;
2124

@@ -29,8 +32,10 @@ class Manifest
2932
// Constants
3033
// =========================================================================
3134

32-
const CACHE_KEY = 'twigpack-transcoder';
33-
const CACHE_TAG = 'twigpack-transcoder';
35+
const ASSET_CLASS = TranscoderAsset::class;
36+
37+
const CACHE_KEY = 'twigpack-' . self::ASSET_CLASS;
38+
const CACHE_TAG = 'twigpack-' . self::ASSET_CLASS;
3439

3540
const DEVMODE_CACHE_DURATION = 1;
3641

@@ -39,11 +44,32 @@ class Manifest
3944
'commons.js',
4045
'vendors.js',
4146
'vendors.css',
47+
'styles.css',
4248
];
4349

4450
// Protected Static Properties
4551
// =========================================================================
4652

53+
protected static $config = [
54+
// If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
55+
'useDevServer' => false,
56+
// Manifest names
57+
'manifest' => [
58+
'legacy' => 'manifest.json',
59+
'modern' => 'manifest.json',
60+
],
61+
// Public server config
62+
'server' => [
63+
'manifestPath' => '/',
64+
'publicPath' => '/',
65+
],
66+
// webpack-dev-server config
67+
'devServer' => [
68+
'manifestPath' => 'http://127.0.0.1:8080',
69+
'publicPath' => '/',
70+
],
71+
];
72+
4773
/**
4874
* @var array
4975
*/
@@ -58,78 +84,85 @@ class Manifest
5884
// =========================================================================
5985

6086
/**
61-
* @param array $config
62-
* @param string $moduleName
63-
* @param bool $async
87+
* Simulate a static constructor
6488
*
65-
* @return string
66-
* @throws NotFoundHttpException
89+
* ManifestVariable constructor.
90+
* @noinspection MagicMethodsValidityInspection
6791
*/
68-
public static function getCssModuleTags(array $config, string $moduleName, bool $async): string
92+
public static function __constructStatic()
6993
{
70-
$legacyModule = self::getModule($config, $moduleName, 'legacy', true);
71-
if ($legacyModule === null) {
72-
return '';
73-
}
74-
$lines = [];
75-
if ($async) {
76-
$lines[] = "<link rel=\"preload\" href=\"{$legacyModule}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\" />";
77-
$lines[] = "<noscript><link rel=\"stylesheet\" href=\"{$legacyModule}\"></noscript>";
78-
} else {
79-
$lines[] = "<link rel=\"stylesheet\" href=\"{$legacyModule}\" />";
94+
self::invalidateCaches();
95+
$assetClass = self::ASSET_CLASS;
96+
$bundle = new $assetClass;
97+
$baseAssetsUrl = Craft::$app->assetManager->getPublishedUrl(
98+
$bundle->sourcePath,
99+
true
100+
);
101+
self::$config['server']['manifestPath'] = Craft::getAlias($bundle->sourcePath);
102+
self::$config['server']['publicPath'] = $baseAssetsUrl;
103+
$useDevServer = getenv('NYS_PLUGIN_DEVSERVER');
104+
if ($useDevServer !== false) {
105+
self::$config['useDevServer'] = (bool)$useDevServer;
80106
}
81-
82-
return implode("\r\n", $lines);
83107
}
84108

85109
/**
86-
* @param string $path
110+
* Get the passed in JS modules from the manifest, and register them in the current Craft view
87111
*
88-
* @return string
112+
* @param array $modules
113+
* @throws NotFoundHttpException
114+
* @throws InvalidConfigException
89115
*/
90-
public static function getCssInlineTags(string $path): string
116+
public static function registerJsModules(array $modules)
91117
{
92-
$result = self::getFile($path);
93-
if ($result) {
94-
$result = "<style>\r\n".$result."</style>\r\n";
95-
return $result;
118+
$view = Craft::$app->getView();
119+
foreach($modules as $module) {
120+
$jsModule = self::getModule(self::$config, $module, 'modern');
121+
if ($jsModule) {
122+
$view->registerJsFile($jsModule, [
123+
'depends' => self::ASSET_CLASS
124+
]);
125+
}
96126
}
97-
98-
return '';
99127
}
100128

101129
/**
102-
* Returns the uglified loadCSS rel=preload Polyfill as per:
103-
* https://github.com/filamentgroup/loadCSS#how-to-use-loadcss-recommended-example
130+
* Get the passed in CS modules from the manifest, and register them in the current Craft view
104131
*
105-
* @return string
132+
* @param array $modules
133+
* @throws NotFoundHttpException
134+
* @throws InvalidConfigException
106135
*/
107-
public static function getCssRelPreloadPolyfill(): string
136+
public static function registerCssModules(array $modules)
108137
{
109-
return <<<EOT
110-
<script>
111-
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
112-
!function(t){"use strict";t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName("link"),n=0;n<a.length;n++){var o=a[n];"preload"!==o.rel||"style"!==o.getAttribute("as")||o.getAttribute("data-loadcss")||(o.setAttribute("data-loadcss",!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener("load",function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent("onload",function(){e.poly(),t.clearInterval(a)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
113-
</script>
114-
EOT;
138+
$view = Craft::$app->getView();
139+
foreach($modules as $module) {
140+
$cssModule = self::getModule(self::$config, $module, 'legacy');
141+
if ($cssModule) {
142+
$view->registerCssFile($cssModule, [
143+
'depends' => self::ASSET_CLASS
144+
]);
145+
}
146+
}
115147
}
116148

117149
/**
118-
* @param array $config
150+
* Get the passed in JS module from the manifest, then output a `<script src="">` tag for it in the HTML
151+
*
119152
* @param string $moduleName
120153
* @param bool $async
121154
*
122155
* @return null|string
123156
* @throws NotFoundHttpException
124157
*/
125-
public static function getJsModuleTags(array $config, string $moduleName, bool $async)
158+
public static function includeJsModule(string $moduleName, bool $async)
126159
{
127-
$legacyModule = self::getModule($config, $moduleName, 'legacy');
160+
$legacyModule = self::getModule(self::$config, $moduleName, 'legacy');
128161
if ($legacyModule === null) {
129162
return '';
130163
}
131164
if ($async) {
132-
$modernModule = self::getModule($config, $moduleName, 'modern');
165+
$modernModule = self::getModule(self::$config, $moduleName, 'modern');
133166
if ($modernModule === null) {
134167
return '';
135168
}
@@ -146,33 +179,34 @@ public static function getJsModuleTags(array $config, string $moduleName, bool $
146179
}
147180

148181
/**
149-
* Safari 10.1 supports modules, but does not support the `nomodule`
150-
* attribute - it will load <script nomodule> anyway. This snippet solve
151-
* this problem, but only for script tags that load external code, e.g.:
152-
* <script nomodule src="nomodule.js"></script>
153-
*
154-
* Again: this will **not* # prevent inline script, e.g.:
155-
* <script nomodule>alert('no modules');</script>.
182+
* Get the passed in CS module from the manifest, then output a `<link>` tag for it in the HTML
156183
*
157-
* This workaround is possible because Safari supports the non-standard
158-
* 'beforeload' event. This allows us to trap the module and nomodule load.
159-
*
160-
* Note also that `nomodule` is supported in later versions of Safari -
161-
* it's just 10.1 that omits this attribute.
162-
*
163-
* c.f.: https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc
184+
* @param string $moduleName
185+
* @param bool $async
164186
*
165187
* @return string
188+
* @throws NotFoundHttpException
166189
*/
167-
public static function getSafariNomoduleFix(): string
190+
public static function includeCssModule(string $moduleName, bool $async): string
168191
{
169-
return <<<EOT
170-
<script>
171-
!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();
172-
</script>
173-
EOT;
192+
$legacyModule = self::getModule(self::$config, $moduleName, 'legacy', true);
193+
if ($legacyModule === null) {
194+
return '';
195+
}
196+
$lines = [];
197+
if ($async) {
198+
$lines[] = "<link rel=\"preload\" href=\"{$legacyModule}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\" />";
199+
$lines[] = "<noscript><link rel=\"stylesheet\" href=\"{$legacyModule}\"></noscript>";
200+
} else {
201+
$lines[] = "<link rel=\"stylesheet\" href=\"{$legacyModule}\" />";
202+
}
203+
204+
return implode("\r\n", $lines);
174205
}
175206

207+
// Protected Static Methods
208+
// =========================================================================
209+
176210
/**
177211
* Return the URI to a module
178212
*
@@ -184,7 +218,7 @@ public static function getSafariNomoduleFix(): string
184218
* @return null|string
185219
* @throws NotFoundHttpException
186220
*/
187-
public static function getModule(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
221+
protected static function getModule(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
188222
{
189223
// Get the module entry
190224
$module = self::getModuleEntry($config, $moduleName, $type, $soft);
@@ -225,7 +259,7 @@ public static function getModule(array $config, string $moduleName, string $type
225259
* @return null|string
226260
* @throws NotFoundHttpException
227261
*/
228-
public static function getModuleEntry(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
262+
protected static function getModuleEntry(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
229263
{
230264
$module = null;
231265
// Get the manifest file
@@ -259,7 +293,7 @@ public static function getModuleEntry(array $config, string $moduleName, string
259293
* @return null|array
260294
* @throws NotFoundHttpException
261295
*/
262-
public static function getManifestFile(array $config, string $type = 'modern')
296+
protected static function getManifestFile(array $config, string $type = 'modern')
263297
{
264298
$manifest = null;
265299
// Determine whether we should use the devServer for HMR or not
@@ -294,44 +328,6 @@ public static function getManifestFile(array $config, string $type = 'modern')
294328
return $manifest;
295329
}
296330

297-
/**
298-
* Returns the contents of a file from a URI path
299-
*
300-
* @param string $path
301-
*
302-
* @return string
303-
*/
304-
public static function getFile(string $path): string
305-
{
306-
return self::getFileFromUri($path, null) ?? '';
307-
}
308-
309-
/**
310-
* @param array $config
311-
* @param string $fileName
312-
* @param string $type
313-
*
314-
* @return string
315-
*/
316-
public static function getFileFromManifest(array $config, string $fileName, string $type = 'legacy'): string
317-
{
318-
try {
319-
$path = self::getModuleEntry($config, $fileName, $type, true);
320-
} catch (NotFoundHttpException $e) {
321-
Craft::error($e->getMessage(), __METHOD__);
322-
}
323-
if ($path !== null) {
324-
$path = self::combinePaths(
325-
$config['localFiles']['basePath'],
326-
$path
327-
);
328-
329-
return self::getFileFromUri($path, null) ?? '';
330-
}
331-
332-
return '';
333-
}
334-
335331
/**
336332
* Return the contents of a JSON file from a URI path
337333
*
@@ -341,7 +337,7 @@ public static function getFileFromManifest(array $config, string $fileName, stri
341337
*/
342338
protected static function getJsonFile(string $path)
343339
{
344-
return self::getFileFromUri($path, [self::class, 'jsonFileDecode']);
340+
return self::getFileFromUri($path, [JsonHelper::class, 'decodeIfJson']);
345341
}
346342

347343
/**
@@ -354,9 +350,6 @@ public static function invalidateCaches()
354350
Craft::info('All manifest caches cleared', __METHOD__);
355351
}
356352

357-
// Protected Static Methods
358-
// =========================================================================
359-
360353
/**
361354
* Return the contents of a file from a URI path
362355
*
@@ -370,7 +363,7 @@ protected static function getFileFromUri(string $path, callable $callback = null
370363
// Resolve any aliases
371364
$alias = Craft::getAlias($path, false);
372365
if ($alias) {
373-
$path = $alias;
366+
$path = (string)$alias;
374367
}
375368
// Make sure it's a full URL
376369
if (!UrlHelper::isAbsoluteUrl($path) && !is_file($path)) {
@@ -442,7 +435,7 @@ function () use ($path, $callback) {
442435
*/
443436
protected static function combinePaths(string ...$paths): string
444437
{
445-
$last_key = \count($paths) - 1;
438+
$last_key = count($paths) - 1;
446439
array_walk($paths, function (&$val, $key) use ($last_key) {
447440
switch ($key) {
448441
case 0:
@@ -480,17 +473,7 @@ protected static function reportError(string $error, $soft = false)
480473
}
481474
Craft::error($error, __METHOD__);
482475
}
483-
484-
// Private Static Methods
485-
// =========================================================================
486-
487-
/**
488-
* @param $string
489-
*
490-
* @return mixed
491-
*/
492-
private static function jsonFileDecode($string)
493-
{
494-
return JsonHelper::decodeIfJson($string);
495-
}
496476
}
477+
478+
// Simulate a static constructor
479+
Manifest::__constructStatic();

0 commit comments

Comments
 (0)