1111
1212namespace nystudio107 \transcoder \helpers ;
1313
14+ use nystudio107 \transcoder \assetbundles \transcoder \TranscoderAsset ;
15+
1416use Craft ;
1517use craft \helpers \Json as JsonHelper ;
1618use craft \helpers \UrlHelper ;
1719
1820use yii \base \Exception ;
21+ use yii \base \InvalidConfigException ;
1922use yii \caching \TagDependency ;
2023use 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