-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimize JSX import source detection (#5498)
* Optimize JSX import source detection * Skip type import check
- Loading branch information
Showing
3 changed files
with
66 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'astro': patch | ||
--- | ||
|
||
Optimize JSX import source detection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { TsConfigJson } from 'tsconfig-resolver'; | ||
import { AstroRenderer } from '../@types/astro'; | ||
import { parseNpmName } from '../core/util.js'; | ||
|
||
export async function detectImportSource( | ||
code: string, | ||
jsxRenderers: Map<string, AstroRenderer>, | ||
tsConfig?: TsConfigJson | ||
): Promise<string | undefined> { | ||
let importSource = detectImportSourceFromComments(code); | ||
if (!importSource && /import/.test(code)) { | ||
importSource = await detectImportSourceFromImports(code, jsxRenderers); | ||
} | ||
if (!importSource && tsConfig) { | ||
importSource = tsConfig.compilerOptions?.jsxImportSource; | ||
} | ||
return importSource; | ||
} | ||
|
||
// Matches import statements and dynamic imports. Captures import specifiers only. | ||
// Adapted from: https://github.com/vitejs/vite/blob/97f8b4df3c9eb817ab2669e5c10b700802eec900/packages/vite/src/node/optimizer/scan.ts#L47-L48 | ||
const importsRE = | ||
/(?<!\/\/.*)(?<=^|;|\*\/)\s*(?:import(?!\s+type)(?:[\w*{}\n\r\t, ]+from)?\s*("[^"]+"|'[^']+')\s*(?=$|;|\/\/|\/\*)|import\s*\(\s*("[^"]+"|'[^']+')\s*\))/gm; | ||
|
||
/** | ||
* Scan a file's imports to detect which renderer it may need. | ||
* ex: if the file imports "preact", it's safe to assume the | ||
* component should be built as a Preact component. | ||
* If no relevant imports found, return undefined. | ||
*/ | ||
async function detectImportSourceFromImports( | ||
code: string, | ||
jsxRenderers: Map<string, AstroRenderer> | ||
): Promise<string | undefined> { | ||
let m; | ||
importsRE.lastIndex = 0; | ||
while ((m = importsRE.exec(code)) != null) { | ||
const spec = (m[1] || m[2]).slice(1, -1); | ||
const pkg = parseNpmName(spec); | ||
if (pkg && jsxRenderers.has(pkg.name)) { | ||
return pkg.name; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Scan a file for an explicit @jsxImportSource comment. | ||
* If one is found, return it's value. Otherwise, return undefined. | ||
*/ | ||
function detectImportSourceFromComments(code: string): string | undefined { | ||
// if no imports were found, look for @jsxImportSource comment | ||
const multiline = code.match(/\/\*\*?[\S\s]*\*\//gm) || []; | ||
for (const comment of multiline) { | ||
const [_, lib] = comment.slice(0, -2).match(/@jsxImportSource\s*(\S+)/) || []; | ||
if (lib) { | ||
return lib.trim(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters