1818use Symfony \Component \AssetMapper \ImportMap \ImportMapConfigReader ;
1919use Symfony \Component \AssetMapper \ImportMap \JavaScriptImport ;
2020use Symfony \Component \AssetMapper \MappedAsset ;
21+ use Symfony \Component \Filesystem \Path ;
2122
2223/**
2324 * Resolves import paths in JS files.
2627 */
2728final class JavaScriptImportPathCompiler implements AssetCompilerInterface
2829{
29- use AssetCompilerPathResolverTrait;
30-
3130 // https://regex101.com/r/fquriB/1
3231 private const IMPORT_PATTERN = '/(?:import\s*(?:(?:\*\s*as\s+\w+|[\w\s{},*]+)\s*from\s*)?|\bimport\()\s*[ \'"`](\.\/[^ \'"`]+|(\.\.\/)*[^ \'"`]+)[ \'"`]\s*[;\)]?/m ' ;
3332
@@ -62,15 +61,19 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
6261 $ dependentAsset = $ this ->findAssetForRelativeImport ($ importedModule , $ asset , $ assetMapper );
6362 }
6463
64+ if (!$ dependentAsset ) {
65+ return $ fullImportString ;
66+ }
67+
6568 // List as a JavaScript import.
6669 // This will cause the asset to be included in the importmap (for relative imports)
6770 // and will be used to generate the preloads in the importmap.
6871 $ isLazy = str_contains ($ fullImportString , 'import( ' );
69- $ addToImportMap = $ isRelativeImport && $ dependentAsset ;
72+ $ addToImportMap = $ isRelativeImport ;
7073 $ asset ->addJavaScriptImport (new JavaScriptImport (
7174 $ addToImportMap ? $ dependentAsset ->publicPathWithoutDigest : $ importedModule ,
72- $ isLazy ,
7375 $ dependentAsset ,
76+ $ isLazy ,
7477 $ addToImportMap ,
7578 ));
7679
@@ -80,7 +83,7 @@ public function compile(string $content, MappedAsset $asset, AssetMapperInterfac
8083 }
8184
8285 // support possibility where the final public files have moved relative to each other
83- $ relativeImportPath = $ this -> createRelativePath ( $ asset ->publicPathWithoutDigest , $ dependentAsset ->publicPathWithoutDigest );
86+ $ relativeImportPath = Path:: makeRelative ( $ dependentAsset ->publicPathWithoutDigest , \dirname ( $ asset ->publicPathWithoutDigest ) );
8487 $ relativeImportPath = $ this ->makeRelativeForJavaScript ($ relativeImportPath );
8588
8689 return str_replace ($ importedModule , $ relativeImportPath , $ fullImportString );
@@ -145,17 +148,21 @@ private function findAssetForBareImport(string $importedModule, AssetMapperInter
145148 return null ;
146149 }
147150
148- if ($ asset = $ assetMapper ->getAsset ($ importMapEntry ->path )) {
149- return $ asset ;
150- }
151+ try {
152+ if ($ asset = $ assetMapper ->getAsset ($ importMapEntry ->path )) {
153+ return $ asset ;
154+ }
151155
152- return $ assetMapper ->getAssetFromSourcePath ($ importMapEntry ->path );
156+ return $ assetMapper ->getAssetFromSourcePath ($ importMapEntry ->path );
157+ } catch (CircularAssetsException $ exception ) {
158+ return $ exception ->getIncompleteMappedAsset ();
159+ }
153160 }
154161
155162 private function findAssetForRelativeImport (string $ importedModule , MappedAsset $ asset , AssetMapperInterface $ assetMapper ): ?MappedAsset
156163 {
157164 try {
158- $ resolvedPath = $ this -> resolvePath (\dirname ($ asset ->logicalPath ), $ importedModule );
165+ $ resolvedSourcePath = Path:: join (\dirname ($ asset ->sourcePath ), $ importedModule );
159166 } catch (RuntimeException $ e ) {
160167 // avoid warning about vendor imports - these are often comments
161168 if (!$ asset ->isVendor ) {
@@ -165,26 +172,36 @@ private function findAssetForRelativeImport(string $importedModule, MappedAsset
165172 return null ;
166173 }
167174
168- $ dependentAsset = $ assetMapper ->getAsset ($ resolvedPath );
175+ try {
176+ $ dependentAsset = $ assetMapper ->getAssetFromSourcePath ($ resolvedSourcePath );
177+ } catch (CircularAssetsException $ exception ) {
178+ $ dependentAsset = $ exception ->getIncompleteMappedAsset ();
179+ }
169180
170181 if ($ dependentAsset ) {
171182 return $ dependentAsset ;
172183 }
173184
185+ // avoid warning about vendor imports - these are often comments
186+ if ($ asset ->isVendor ) {
187+ return null ;
188+ }
189+
174190 $ message = sprintf ('Unable to find asset "%s" imported from "%s". ' , $ importedModule , $ asset ->sourcePath );
175191
176- try {
177- if (null !== $ assetMapper ->getAsset (sprintf ('%s.js ' , $ resolvedPath ))) {
178- $ message .= sprintf (' Try adding ".js" to the end of the import - i.e. "%s.js". ' , $ importedModule );
192+ if (is_file ($ resolvedSourcePath )) {
193+ $ message .= sprintf ('The file "%s" exists, but it is not in a mapped asset path. Add it to the "paths" config. ' , $ resolvedSourcePath );
194+ } else {
195+ try {
196+ if (null !== $ assetMapper ->getAssetFromSourcePath (sprintf ('%s.js ' , $ resolvedSourcePath ))) {
197+ $ message .= sprintf (' Try adding ".js" to the end of the import - i.e. "%s.js". ' , $ importedModule );
198+ }
199+ } catch (CircularAssetsException ) {
200+ // avoid circular error if there is self-referencing import comments
179201 }
180- } catch (CircularAssetsException ) {
181- // avoid circular error if there is self-referencing import comments
182202 }
183203
184- // avoid warning about vendor imports - these are often comments
185- if (!$ asset ->isVendor ) {
186- $ this ->handleMissingImport ($ message );
187- }
204+ $ this ->handleMissingImport ($ message );
188205
189206 return null ;
190207 }
0 commit comments