diff --git a/src/Common/Service/Asset.php b/src/Common/Service/Asset.php
index e2fdb4a8..55336119 100644
--- a/src/Common/Service/Asset.php
+++ b/src/Common/Service/Asset.php
@@ -563,6 +563,7 @@ public function addLibrary(string $sKey, array $aUrls): self
* @param string|null $sForceType The asset's file type (e.g., JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
+ * @param bool|null $bModule Whether asset is a JS module or not (null = undefined)
*
* @return $this
* @throws AssetException
@@ -572,7 +573,8 @@ public function load(
string $sAssetLocation = null,
string $sForceType = null,
bool $bAsync = false,
- bool $bDefer = false
+ bool $bDefer = false,
+ bool $bModule = null
): self {
$aAssets = (array) $mAssets;
@@ -600,13 +602,13 @@ public function load(
foreach ($aAssets as $sAsset) {
if (preg_match('#^https?://#', $sAsset)) {
- $this->loadUrl($sAsset, $sForceType, $bAsync, $bDefer);
+ $this->loadUrl($sAsset, $sForceType, $bAsync, $bDefer, $bModule);
} elseif (substr($sAsset, 0, 0) === '/') {
- $this->loadAbsolute(substr($sAsset, 1), $sForceType, $bAsync, $bDefer);
+ $this->loadAbsolute(substr($sAsset, 1), $sForceType, $bAsync, $bDefer, $bModule);
} else {
- $this->{$sAssetLocationMethod}($sAsset, $sForceType, $bAsync, $bDefer, $sAssetLocation);
+ $this->{$sAssetLocationMethod}($sAsset, $sForceType, $bAsync, $bDefer, $bModule, $sAssetLocation);
}
}
@@ -624,11 +626,12 @@ public function load(
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
+ * @param bool|null $bModule Whether asset is a JS module or not (null = undefined)
*
* @return $this
* @throws AssetException
*/
- protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
+ protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, bool $bModule = null): self
{
$sType = $this->determineType($sAsset, $sForceType);
@@ -640,11 +643,11 @@ protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync, bo
case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
- $this->aJs['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer];
+ $this->aJs['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer, $bModule];
break;
case static::TYPE_JS_HEADER:
- $this->aJsHeader['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer];
+ $this->aJsHeader['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer, $bModule];
break;
}
@@ -660,11 +663,12 @@ protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync, bo
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
+ * @param bool|null $bModule Whether asset is a JS module or not (null = undefined)
*
* @return $this
* @throws AssetException
*/
- protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
+ protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, bool $bModule = null): self
{
$sType = $this->determineType($sAsset, $sForceType);
@@ -676,11 +680,11 @@ protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsyn
case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
- $this->aJs['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer];
+ $this->aJs['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer, $bModule];
break;
case static::TYPE_JS_HEADER:
- $this->aJsHeader['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer];
+ $this->aJsHeader['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer, $bModule];
break;
}
@@ -757,15 +761,31 @@ public function output(string $sType = self::TYPE_ALL, bool $bOutput = true): ar
// Linked JS
if (!empty($this->aJs) && ($sType === static::TYPE_JS || $sType === static::TYPE_ALL)) {
foreach ($this->aJs as $aAsset) {
- [$sAsset, $bAsync, $bDefer] = $aAsset;
- $aOut[] = '';
+ [$sAsset, $bAsync, $bDefer, $bModule] = $aAsset;
+ $aOut[] = sprintf(
+ '',
+ $sAsset,
+ $bAsync ? 'async ' : '',
+ $bDefer ? 'defer ' : '',
+ isset($bModule)
+ ? ($bModule ? 'type="module"' : 'nomodule') . ' '
+ : ''
+ );
}
}
if (!empty($this->aJsHeader) && ($sType === static::TYPE_JS_HEADER || $sType === static::TYPE_ALL)) {
foreach ($this->aJsHeader as $aAsset) {
- [$sAsset, $bAsync, $bDefer] = $aAsset;
- $aOut[] = '';
+ [$sAsset, $bAsync, $bDefer, $bModule] = $aAsset;
+ $aOut[] = sprintf(
+ '',
+ $sAsset,
+ $bAsync ? ' async' : '',
+ $bDefer ? ' defer' : '',
+ isset($bModule)
+ ? ' ' . ($bModule ? 'type="module"' : 'nomodule')
+ : ''
+ );
}
}
@@ -935,11 +955,12 @@ public function inline($mScript = null, string $sForceType = null, $sJsLocation
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
* @param array|string $mModule The module to load from
+ * @param bool|null $bModule Whether asset is a JS module or not (null = undefined)
*
* @return $this
* @throws AssetException
*/
- protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, $mModule): self
+ protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, bool $bModule = null, $mModule): self
{
if (is_array($mModule)) {
$sModule = !empty($mModule[0]) ? $mModule[0] : null;
@@ -964,6 +985,7 @@ protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync,
$this->addCacheBuster($this->sBaseModuleUrl . $sModule . '/assets/js/' . $sAsset),
$bAsync,
$bDefer,
+ $bModule,
];
break;
@@ -972,6 +994,7 @@ protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync,
$this->addCacheBuster($this->sBaseModuleUrl . $sModule . '/assets/js/' . $sAsset),
$bAsync,
$bDefer,
+ $bModule,
];
break;
}
@@ -1111,11 +1134,12 @@ public function getCacheBuster(): ?string
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
+ * @param bool|null $bModule Whether asset is a JS module or not (null = undefined)
*
* @return $this
* @throws AssetException
*/
- protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
+ protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, bool $bModule = null): self
{
$sType = $this->determineType($sAsset, $sForceType);
@@ -1127,11 +1151,21 @@ protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync, bo
case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
- $this->aJs['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync, $bDefer];
+ $this->aJs['APP-' . $sAsset] = [
+ $this->buildUrl($this->sJsDir . $sAsset),
+ $bAsync,
+ $bDefer,
+ $bModule,
+ ];
break;
case static::TYPE_JS_HEADER:
- $this->aJsHeader['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync, $bDefer];
+ $this->aJsHeader['APP-' . $sAsset] = [
+ $this->buildUrl($this->sJsDir . $sAsset),
+ $bAsync,
+ $bDefer,
+ $bModule,
+ ];
break;
}