Skip to content

Commit 1fe466b

Browse files
committed
Add support for sharing data in Script Modules and improve documentation
1 parent a8a8ba8 commit 1fe466b

4 files changed

Lines changed: 134 additions & 22 deletions

File tree

docs/assets.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ $module
6969
->withFilePath('/path/to/module.js')
7070
->disableAutodiscoverVersion()
7171
->enableAutodiscoverVersion()
72-
->withVersion('1.0');
72+
->withVersion('1.0')
73+
->withData(['key' => 'value']);
7374

7475
$style = new Style('foo', 'www.example.com/style.css');
7576
$style
@@ -81,7 +82,7 @@ $style
8182

8283
### Enqueue conditionally
8384

84-
You can enqueue your Assets conditionally by using following API:
85+
You can enqueue your Assets conditionally by using the following API:
8586

8687
```php
8788
<?php
@@ -97,7 +98,7 @@ $style->canEnqueue(function(): bool {
9798
});
9899
```
99100

100-
By default Assets are always enqueued.
101+
By default, Assets are always enqueued.
101102

102103
### Location
103104

@@ -318,7 +319,7 @@ $script
318319

319320
### Translation data
320321

321-
Scripts can also have translation data via `wp_set_script_translations()`. This can be added like following:
322+
Scripts can also have translation data via `wp_set_script_translations()`. This can be added like the following:
322323

323324
```php
324325
<?php
@@ -449,6 +450,20 @@ $script->withAttributes(['src' => 'another-script.js']); // Will not overwrite "
449450

450451
WordPress 6.5 introduced Script Modules for native JavaScript ES6 modules. The `ScriptModule` class provides basic asset management with the following limitations:
451452

453+
### Module Data
454+
455+
Scripts Modules allow sharing data from the server to the client via a filter `"script_module_data_{$handle}"`.
456+
457+
Assets registered as `ScriptModule` can have shared data added like following:
458+
459+
```php
460+
$module = new ScriptModule('@my-plugin/main', 'assets/main.js');
461+
$module->withData([
462+
'apiUrl' => get_rest_url(),
463+
'nonce' => wp_create_nonce('wp_rest'),
464+
]);
465+
```
466+
452467
### Usage Examples
453468

454469
```php

src/Handler/ScriptModuleHandler.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
namespace Inpsyde\Assets\Handler;
66

77
use Inpsyde\Assets\Asset;
8+
use Inpsyde\Assets\ScriptModule;
89

910
class ScriptModuleHandler implements AssetHandler
1011
{
1112
public function enqueue(Asset $asset): bool
1213
{
14+
if (!$asset instanceof ScriptModule) {
15+
return false;
16+
}
1317
if (!static::scriptModulesSupported()) {
1418
return false;
1519
}
@@ -27,27 +31,45 @@ public function enqueue(Asset $asset): bool
2731

2832
public function register(Asset $asset): bool
2933
{
34+
if (!$asset instanceof ScriptModule) {
35+
return false;
36+
}
3037
if (!static::scriptModulesSupported()) {
3138
return false;
3239
}
3340

3441
$handle = $asset->handle();
3542

43+
$this->shareData($asset);
44+
3645
wp_register_script_module(
3746
$handle,
3847
$asset->url(),
3948
$asset->dependencies(), // @phpstan-ignore-line
40-
$asset->version()
49+
$asset->version(),
4150
);
4251

4352
return true;
4453
}
4554

46-
public static function scriptModulesSupported(): bool
55+
protected static function scriptModulesSupported(): bool
4756
{
48-
return function_exists('wp_register_script_module')
49-
&& function_exists('wp_enqueue_script_module')
50-
&& function_exists('wp_deregister_script_module')
51-
&& function_exists('wp_dequeue_script_module');
57+
return class_exists('WP_Script_Modules');
58+
}
59+
60+
protected function shareData(ScriptModule $asset): void
61+
{
62+
$handle = $asset->handle();
63+
64+
if (!$asset->data()) {
65+
return;
66+
}
67+
68+
add_filter(
69+
"script_module_data_{$handle}",
70+
static function (array $data) use ($asset): array {
71+
return array_merge($data, $asset->data());
72+
}
73+
);
5274
}
5375
}

src/ScriptModule.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,37 @@ class ScriptModule extends BaseAsset implements Asset
1010
{
1111
use DependencyExtractionTrait;
1212

13+
/**
14+
* Data which will be added via ...
15+
* - WP_Script::add_data()
16+
* - WP_Style::add_data()
17+
*
18+
* @var array<string, mixed>
19+
*/
20+
protected array $data = [];
21+
22+
/**
23+
* @return array<string, mixed>
24+
*/
25+
public function data(): array
26+
{
27+
return $this->data;
28+
}
29+
30+
/**
31+
* Allows to set additional data via WP_Script::add_data() or WP_Style::add_data().
32+
*
33+
* @param array<string, mixed> $data
34+
*
35+
* @return static
36+
*/
37+
public function withData(array $data): Asset
38+
{
39+
$this->data = array_merge($this->data, $data);
40+
41+
return $this;
42+
}
43+
1344
/**
1445
* {@inheritDoc}
1546
*/

tests/phpunit/Unit/Handler/ScriptModuleHandlerTest.php

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
namespace Inpsyde\Assets\Tests\Unit\Handler;
66

77
use Brain\Monkey\Functions;
8-
use Inpsyde\Assets\Asset;
8+
use Brain\Monkey\Filters;
99
use Inpsyde\Assets\Handler\AssetHandler;
10-
use Inpsyde\Assets\Handler\OutputFilterAwareAssetHandler;
1110
use Inpsyde\Assets\Handler\ScriptModuleHandler;
11+
use Inpsyde\Assets\Script;
1212
use Inpsyde\Assets\ScriptModule;
1313
use Inpsyde\Assets\Tests\Unit\AbstractTestCase;
1414

@@ -29,8 +29,8 @@ public function testBasic(): void
2929
*/
3030
public function testRegisterEnqueue(): void
3131
{
32-
$handler = new class extends ScriptModuleHandler {
33-
public static function scriptModulesSupported(): bool
32+
$handler = new class extends ScriptModuleHandler{
33+
protected static function scriptModulesSupported(): bool
3434
{
3535
return true;
3636
}
@@ -68,14 +68,9 @@ static function (
6868
/**
6969
* @test
7070
*/
71-
public function testRegisterEnqueueWithoutSupport(): void
71+
public function testSkipEnqueueIfScriptModulesNotSupported(): void
7272
{
73-
$handler = new class extends ScriptModuleHandler {
74-
public static function scriptModulesSupported(): bool
75-
{
76-
return false;
77-
}
78-
};
73+
$handler = new ScriptModuleHandler();
7974

8075
$scriptModule = (new ScriptModule('@my-plugin/module', 'module.js'))
8176
->withVersion('1.0.0')
@@ -89,4 +84,53 @@ public static function scriptModulesSupported(): bool
8984
static::assertFalse($result);
9085
}
9186

92-
}
87+
public function testSkipRegisterIfScriptModulesNotSupported(): void
88+
{
89+
$handler = new ScriptModuleHandler();
90+
91+
$scriptModule = (new ScriptModule('@my-plugin/module', 'module.js'))
92+
->withVersion('1.0.0')
93+
->withDependencies('@wordpress/interactivity');
94+
95+
Functions\expect('wp_register_script_module')->never();
96+
Functions\expect('wp_enqueue_script_module')->never();
97+
98+
$result = $handler->register($scriptModule);
99+
100+
static::assertFalse($result);
101+
}
102+
103+
public function testSkipNonScriptModuleRegistration(): void
104+
{
105+
$handler = new ScriptModuleHandler();
106+
$scriptModule = new Script('@my-plugin/script', 'script.js');
107+
108+
Functions\expect('wp_register_script_module')->never();
109+
110+
$result = $handler->register($scriptModule);
111+
112+
static::assertFalse($result);
113+
}
114+
115+
public function testDataSharedViaFilter(): void
116+
{
117+
$handler = new class extends ScriptModuleHandler{
118+
protected static function scriptModulesSupported(): bool
119+
{
120+
return true;
121+
}
122+
};
123+
124+
$scriptModule = (new ScriptModule('@my-plugin/module', 'module.js'))
125+
->withVersion('1.0.0')
126+
->withDependencies('@wordpress/interactivity')
127+
->withData(['key' => 'value']);
128+
129+
Functions\expect('wp_register_script_module')->once();
130+
Filters\expectAdded("script_module_data_@my-plugin/module");
131+
132+
$result = $handler->register($scriptModule);
133+
134+
static::assertTrue($result);
135+
}
136+
}

0 commit comments

Comments
 (0)