Skip to content

Commit 3818c48

Browse files
committed
collect components separately
1 parent 69ce58e commit 3818c48

File tree

13 files changed

+745
-131
lines changed

13 files changed

+745
-131
lines changed

generatable.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
"label": "Blade components",
5050
"features": [
5151
"link",
52-
"completion"
52+
"completion",
53+
"hover"
5354
]
5455
},
5556
{

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@
194194
"generated": true,
195195
"description": "Enable completion for Blade components."
196196
},
197+
"Laravel.bladeComponent.hover": {
198+
"type": "boolean",
199+
"default": true,
200+
"generated": true,
201+
"description": "Enable hover information for Blade components."
202+
},
197203
"Laravel.config.diagnostics": {
198204
"type": "boolean",
199205
"default": true,

php-templates/blade-components.php

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?php
2+
3+
$components = new class {
4+
protected $autoloaded = [];
5+
6+
public function __construct()
7+
{
8+
$this->autoloaded = require base_path("vendor/composer/autoload_psr4.php");
9+
}
10+
11+
public function all()
12+
{
13+
return collect(array_merge(
14+
$this->getStandardClasses(),
15+
$this->getStandardViews(),
16+
$this->getNamespaced(),
17+
$this->getAnonymousNamespaced(),
18+
$this->getAnonymous(),
19+
$this->getAliases(),
20+
))->groupBy('key')->map(fn($items) => [
21+
'isVendor' => $items->first()['isVendor'],
22+
'paths' => $items->pluck('path')->values(),
23+
]);
24+
}
25+
26+
protected function getStandardViews()
27+
{
28+
$path = resource_path('views/components');
29+
30+
return $this->findFiles($path, 'blade.php');
31+
}
32+
33+
protected function findFiles($path, $extension, $keyCallback = null)
34+
{
35+
if (!is_dir($path)) {
36+
return [];
37+
}
38+
39+
$files = \Symfony\Component\Finder\Finder::create()
40+
->files()
41+
->name("*." . $extension)
42+
->in($path);
43+
44+
foreach ($files as $file) {
45+
$realPath = $file->getRealPath();
46+
47+
$key = \Illuminate\Support\Str::of($realPath)
48+
->replace(realpath($path), '')
49+
->ltrim('/\\')
50+
->replace('.' . $extension, '')
51+
->replace(['/', '\\'], '.');
52+
53+
$components[] = [
54+
"path" => LaravelVsCode::relativePath($realPath),
55+
"isVendor" => LaravelVsCode::isVendor($realPath),
56+
"key" => $keyCallback ? $keyCallback($key) : $key,
57+
];
58+
}
59+
60+
return $components;
61+
}
62+
63+
protected function getStandardClasses()
64+
{
65+
$path = app_path('View/Components');
66+
67+
return $this->findFiles(
68+
$path,
69+
'php',
70+
fn($key) => $key->explode('.')
71+
->map(fn($p) => \Illuminate\Support\Str::kebab($p))
72+
->implode('.'),
73+
);
74+
}
75+
76+
protected function getAliases()
77+
{
78+
$components = [];
79+
80+
foreach (\Illuminate\Support\Facades\Blade::getClassComponentAliases() as $key => $class) {
81+
if (class_exists($class)) {
82+
$reflection = new ReflectionClass($class);
83+
84+
$components[] = [
85+
"path" => LaravelVsCode::relativePath($reflection->getFileName()),
86+
"isVendor" => LaravelVsCode::isVendor($reflection->getFileName()),
87+
"key" => $key,
88+
];
89+
}
90+
}
91+
92+
return $components;
93+
}
94+
95+
protected function getExtensions()
96+
{
97+
// \Illuminate\Support\Facades\Blade::getExtensions(),
98+
return [];
99+
}
100+
101+
protected function getAnonymousNamespaced()
102+
{
103+
// \Illuminate\Support\Facades\Blade::getAnonymousComponentNamespaces();
104+
return [];
105+
}
106+
107+
protected function getAnonymous()
108+
{
109+
$components = [];
110+
111+
foreach (\Illuminate\Support\Facades\Blade::getAnonymousComponentPaths() as $item) {
112+
array_push(
113+
$components,
114+
...$this->findFiles(
115+
$item['path'],
116+
'blade.php',
117+
fn($key) => $key
118+
->kebab()
119+
->prepend(($item['prefix'] ?? ':') . ':')
120+
->ltrim(':')
121+
->when(true, function ($str) {
122+
if ($str->endsWith('.index')) {
123+
return $str->replaceLast('.index', '');
124+
}
125+
126+
if (!$str->contains('.')) {
127+
return $str;
128+
}
129+
130+
$parts = $str->explode('.');
131+
132+
if ($parts->slice(-2)->unique()->count() === 1) {
133+
$parts->pop();
134+
135+
return $str->of($parts->implode('.'));
136+
}
137+
138+
return $str;
139+
})
140+
)
141+
);
142+
}
143+
144+
return $components;
145+
}
146+
147+
protected function getNamespaced()
148+
{
149+
$namespaced = \Illuminate\Support\Facades\Blade::getClassComponentNamespaces();
150+
$components = [];
151+
152+
foreach ($namespaced as $key => $classNamespace) {
153+
$path = $this->getNamespacePath($classNamespace);
154+
155+
if (!$path) {
156+
continue;
157+
}
158+
159+
array_push(
160+
$components,
161+
...$this->findFiles(
162+
$path,
163+
'php',
164+
fn($k) => $k->kebab()->prepend($key . "::"),
165+
)
166+
);
167+
}
168+
169+
return $components;
170+
}
171+
172+
protected function getNamespacePath($classNamespace)
173+
{
174+
foreach ($this->autoloaded as $ns => $paths) {
175+
if (!str_starts_with($classNamespace, $ns)) {
176+
continue;
177+
}
178+
179+
foreach ($paths as $p) {
180+
$dir = \Illuminate\Support\Str::of($classNamespace)
181+
->replace($ns, '')
182+
->replace('\\', '/')
183+
->prepend($p . DIRECTORY_SEPARATOR)
184+
->toString();
185+
186+
if (is_dir($dir)) {
187+
return $dir;
188+
}
189+
}
190+
191+
return null;
192+
}
193+
194+
return null;
195+
}
196+
};
197+
198+
echo json_encode($components->all());

php-templates/bootstrap-laravel.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public static function relativePath($path)
1717
return ltrim(str_replace(base_path(), '', realpath($path)), DIRECTORY_SEPARATOR);
1818
}
1919

20+
public static function isVendor($path)
21+
{
22+
return str_contains($path, base_path("vendor"));
23+
}
24+
2025
public static function outputMarker($key)
2126
{
2227
return '__VSCODE_LARAVEL_' . $key . '__';

php-templates/views.php

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,110 @@
11
<?php
22

33
$blade = new class {
4-
public function findFiles($path)
5-
{
6-
$paths = [];
4+
public function getAllViews()
5+
{
6+
$finder = app("view")->getFinder();
77

8-
if (!is_dir($path)) {
9-
return $paths;
8+
$paths = collect($finder->getPaths())->flatMap(fn($path) => $this->findViews($path));
9+
10+
$hints = collect($finder->getHints())->flatMap(
11+
fn($paths, $key) => collect($paths)->flatMap(
12+
fn($path) => collect($this->findViews($path))->map(
13+
fn($value) => array_merge($value, ["key" => "{$key}::{$value["key"]}"])
14+
)
15+
)
16+
);
17+
18+
[$local, $vendor] = $paths
19+
->merge($hints)
20+
->values()
21+
->partition(fn($v) => !$v["isVendor"]);
22+
23+
return $local
24+
->sortBy("key", SORT_NATURAL)
25+
->merge($vendor->sortBy("key", SORT_NATURAL));
1026
}
1127

12-
$files = \Symfony\Component\Finder\Finder::create()
13-
->files()
14-
->name("*.blade.php")
15-
->in($path);
16-
17-
foreach ($files as $file) {
18-
$paths[] = [
19-
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $file->getRealPath()),
20-
"isVendor" => str_contains($file->getRealPath(), base_path("vendor")),
21-
"key" => \Illuminate\Support\Str::of($file->getRealPath())
22-
->replace(realpath($path), "")
23-
->replace(".blade.php", "")
24-
->ltrim(DIRECTORY_SEPARATOR)
25-
->replace(DIRECTORY_SEPARATOR, ".")
26-
];
28+
public function getAllComponents()
29+
{
30+
$namespaced = \Illuminate\Support\Facades\Blade::getClassComponentNamespaces();
31+
$autoloaded = require base_path("vendor/composer/autoload_psr4.php");
32+
$components = [];
33+
34+
foreach ($namespaced as $key => $ns) {
35+
$path = null;
36+
37+
foreach ($autoloaded as $namespace => $paths) {
38+
if (str_starts_with($ns, $namespace)) {
39+
foreach ($paths as $p) {
40+
$test = \Illuminate\Support\Str::of($ns)->replace($namespace, '')->replace('\\', '/')->prepend($p . DIRECTORY_SEPARATOR)->toString();
41+
42+
if (is_dir($test)) {
43+
$path = $test;
44+
break;
45+
}
46+
}
47+
48+
break;
49+
}
50+
}
51+
52+
if (!$path) {
53+
continue;
54+
}
55+
56+
$files = \Symfony\Component\Finder\Finder::create()
57+
->files()
58+
->name("*.php")
59+
->in($path);
60+
61+
foreach ($files as $file) {
62+
$realPath = $file->getRealPath();
63+
64+
$components[] = [
65+
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $realPath),
66+
"isVendor" => str_contains($realPath, base_path("vendor")),
67+
"key" => \Illuminate\Support\Str::of($realPath)
68+
->replace(realpath($path), "")
69+
->replace(".php", "")
70+
->ltrim(DIRECTORY_SEPARATOR)
71+
->replace(DIRECTORY_SEPARATOR, ".")
72+
->kebab()
73+
->prepend($key . "::"),
74+
];
75+
}
76+
}
77+
78+
return $components;
2779
}
2880

29-
return $paths;
30-
}
81+
protected function findViews($path)
82+
{
83+
$paths = [];
84+
85+
if (!is_dir($path)) {
86+
return $paths;
87+
}
88+
89+
$files = \Symfony\Component\Finder\Finder::create()
90+
->files()
91+
->name("*.blade.php")
92+
->in($path);
93+
94+
foreach ($files as $file) {
95+
$paths[] = [
96+
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $file->getRealPath()),
97+
"isVendor" => str_contains($file->getRealPath(), base_path("vendor")),
98+
"key" => \Illuminate\Support\Str::of($file->getRealPath())
99+
->replace(realpath($path), "")
100+
->replace(".blade.php", "")
101+
->ltrim(DIRECTORY_SEPARATOR)
102+
->replace(DIRECTORY_SEPARATOR, ".")
103+
];
104+
}
105+
106+
return $paths;
107+
}
31108
};
32109

33-
$paths = collect(
34-
app("view")
35-
->getFinder()
36-
->getPaths()
37-
)->flatMap(fn($path) => $blade->findFiles($path));
38-
39-
$hints = collect(
40-
app("view")
41-
->getFinder()
42-
->getHints()
43-
)->flatMap(
44-
fn($paths, $key) => collect($paths)->flatMap(
45-
fn($path) => collect($blade->findFiles($path))->map(
46-
fn($value) => array_merge($value, ["key" => "{$key}::{$value["key"]}"])
47-
)
48-
)
49-
);
50-
51-
[$local, $vendor] = $paths
52-
->merge($hints)
53-
->values()
54-
->partition(fn($v) => !$v["isVendor"]);
55-
56-
echo $local
57-
->sortBy("key", SORT_NATURAL)
58-
->merge($vendor->sortBy("key", SORT_NATURAL))
59-
->toJson();
110+
echo json_encode($blade->getAllViews()->merge($blade->getAllComponents()));

0 commit comments

Comments
 (0)