Skip to content

Commit cafcf2c

Browse files
committed
Add filament scripts attributes
1 parent 4cbda3d commit cafcf2c

5 files changed

Lines changed: 151 additions & 3 deletions

File tree

packages/support/config/filament.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@
5757

5858
'assets_path' => null,
5959

60+
/*
61+
|--------------------------------------------------------------------------
62+
| Script Attributes
63+
|--------------------------------------------------------------------------
64+
| This is an array of attributes that will be added to all script tags
65+
| rendered by Filament. You can use this to add attributes like `data-cfasync` or `async` to
66+
| all scripts, or to add custom data attributes that your application may require.
67+
|
68+
*/
69+
70+
'scripts' => [
71+
'attributes' => [
72+
// 'data-cfasync' => 'false',
73+
],
74+
],
75+
6076
/*
6177
|--------------------------------------------------------------------------
6278
| Cache Path

packages/support/resources/views/assets.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@if (isset($data))
2-
<script>
2+
<script @foreach($dataScriptAttributes ?? [] as $key => $value) @if(is_int($key)) {{ $value }} @else {{ $key }}="{{ $value }}" @endif @endforeach>
33
window.filamentData = @js($data)
44
</script>
55
@endif

packages/support/src/Assets/AssetManager.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public function getScripts(?array $packages = null, bool $withCore = true): arra
189189
/**
190190
* @param array<string> | null $packages
191191
*/
192-
public function renderScripts(?array $packages = null, bool $withCore = false): string
192+
public function renderScripts(?array $packages = null, bool $withCore = false, array $attributes = []): string
193193
{
194194
/** @var array<Js> $assets */
195195
$assets = $this->getScripts($packages, $withCore);
@@ -201,9 +201,17 @@ public function renderScripts(?array $packages = null, bool $withCore = false):
201201
);
202202
}
203203

204+
$globalAttributes = config('filament.scripts.attributes', []);
205+
$mergedAttributes = array_merge($globalAttributes, $attributes);
206+
207+
foreach ($assets as $asset) {
208+
$asset->extraAttributes($mergedAttributes);
209+
}
210+
204211
return view('filament::assets', [
205212
'assets' => $assets,
206213
'data' => $this->getScriptData($packages),
214+
'dataScriptAttributes' => $mergedAttributes,
207215
])->render();
208216
}
209217

packages/support/src/Assets/Js.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ public function getExtraAttributesHtml(): string
150150
$attributes = '';
151151

152152
foreach ($this->getExtraAttributes() as $key => $value) {
153-
$attributes .= " {$key}=\"{$value}\"";
153+
if (is_int($key)) {
154+
$attributes .= " {$value}";
155+
} else {
156+
$attributes .= " {$key}=\"{$value}\"";
157+
}
154158
}
155159

156160
return $attributes;
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
3+
use Filament\Tests\TestCase;
4+
use Illuminate\Support\Facades\Blade;
5+
6+
uses(TestCase::class);
7+
8+
/*
9+
/ Default behavior tests
10+
*/
11+
it('renders script tags without extra attributes', function (): void {
12+
$html = Blade::render('@filamentScripts');
13+
14+
preg_match_all('/<script[\s\S]*?>/m', $html, $matches);
15+
16+
expect($matches[0])->not->toBeEmpty()
17+
->and($html)->not->toContain('data-cfasync');
18+
});
19+
20+
/*
21+
/ Inline attributes tests
22+
*/
23+
24+
it('applies inline attributes to every rendered script tag', function (): void {
25+
$html = Blade::render("@filamentScripts(attributes: ['data-cfasync' => 'false'])");
26+
$htmlWithout = Blade::render('@filamentScripts');
27+
28+
preg_match_all('/<script[\s\S]*?src=[\s\S]*?>/m', $html, $withMatches);
29+
preg_match_all('/<script[\s\S]*?src=[\s\S]*?>/m', $htmlWithout, $withoutMatches);
30+
31+
expect($withMatches[0])->toHaveCount(count($withoutMatches[0]));
32+
33+
foreach ($withMatches[0] as $tag) {
34+
expect($tag)->toContain('data-cfasync="false"');
35+
}
36+
});
37+
38+
/*
39+
/ Keyed vs non-keyed attributes tests
40+
*/
41+
42+
it('renders integer-keyed attributes as normal attributes, not integer keys like 0="async"', function (): void {
43+
$html = Blade::render("@filamentScripts(attributes: ['data-cfasync' => 'false', 'async'])");
44+
45+
expect($html)
46+
->toContain('data-cfasync="false"')
47+
->toContain(' async')
48+
->not->toContain('0="async"')
49+
->not->toContain('="async"');
50+
});
51+
52+
/*
53+
/ FilamentData script block tests
54+
*/
55+
56+
it('applies inline attributes to the filamentData script block', function (): void {
57+
$html = Blade::render("@filamentScripts(attributes: ['data-cfasync' => 'false'])");
58+
59+
expect($html)
60+
->toMatch('/<script[^>]*data-cfasync="false"[^>]*>\s*window\.filamentData/');
61+
});
62+
63+
it('applies global config attributes to the filamentData script block', function (): void {
64+
config(['filament.scripts.attributes' => ['data-cfasync' => 'false']]);
65+
66+
$html = Blade::render('@filamentScripts');
67+
68+
expect($html)
69+
->toMatch('/<script[^>]*data-cfasync="false"[^>]*>\s*window\.filamentData/');
70+
});
71+
72+
it('applies inline attributes to both the filamentData block and all src script tags', function (): void {
73+
$html = Blade::render("@filamentScripts(attributes: ['data-cfasync' => 'false'])");
74+
75+
preg_match_all('/<script[\s\S]*?data-cfasync="false"[\s\S]*?>/m', $html, $matches);
76+
77+
expect(count($matches[0]))->toBeGreaterThanOrEqual(2);
78+
});
79+
80+
/*
81+
/ Global config attributes tests
82+
*/
83+
84+
it('global config attributes apply to every script tag', function (): void {
85+
config(['filament.scripts.attributes' => ['data-cfasync' => 'false']]);
86+
87+
$html = Blade::render('@filamentScripts');
88+
89+
preg_match_all('/<script[\s\S]*?src=[\s\S]*?>/m', $html, $matches);
90+
91+
expect($matches[0])->not->toBeEmpty();
92+
93+
foreach ($matches[0] as $tag) {
94+
expect($tag)->toContain('data-cfasync="false"');
95+
}
96+
});
97+
98+
/*
99+
/ Overriding and merging attributes tests
100+
*/
101+
102+
it('inline attributes override global config attributes for the same key', function (): void {
103+
config(['filament.scripts.attributes' => ['data-cfasync' => 'false']]);
104+
105+
$html = Blade::render("@filamentScripts(attributes: ['data-cfasync' => 'true'])");
106+
107+
expect($html)
108+
->toContain('data-cfasync="true"')
109+
->not->toContain('data-cfasync="false"');
110+
});
111+
112+
it('merges global config attributes with inline attributes', function (): void {
113+
config(['filament.scripts.attributes' => ['data-cfasync' => 'false']]);
114+
115+
$html = Blade::render("@filamentScripts(attributes: ['crossorigin' => 'anonymous'])");
116+
117+
expect($html)
118+
->toContain('data-cfasync="false"')
119+
->toContain('crossorigin="anonymous"');
120+
});

0 commit comments

Comments
 (0)