Read jsxImportSource from tsconfig (#4759)
* Read jsxImportSource from tsconfig * Only read from tsconfig if not found earlier
This commit is contained in:
parent
0398efa39f
commit
fc885eaea1
13 changed files with 118 additions and 17 deletions
5
.changeset/tricky-cats-drop.md
Normal file
5
.changeset/tricky-cats-drop.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Read jsxImportSource from tsconfig
|
|
@ -9,6 +9,7 @@ import type {
|
|||
} from '@astrojs/markdown-remark';
|
||||
import type * as babel from '@babel/core';
|
||||
import type { AddressInfo } from 'net';
|
||||
import type { TsConfigJson } from 'tsconfig-resolver';
|
||||
import type * as vite from 'vite';
|
||||
import { z } from 'zod';
|
||||
import type { SerializedSSRManifest } from '../core/app/types';
|
||||
|
@ -876,6 +877,8 @@ export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
|
|||
// that is different from the user-exposed configuration.
|
||||
// TODO: Create an AstroConfig class to manage this, long-term.
|
||||
_ctx: {
|
||||
tsConfig: TsConfigJson | undefined;
|
||||
tsConfigPath: string | undefined;
|
||||
pageExtensions: string[];
|
||||
injectedRoutes: InjectedRoute[];
|
||||
adapter: AstroAdapter | undefined;
|
||||
|
|
|
@ -11,6 +11,7 @@ import * as colors from 'kleur/colors';
|
|||
import path from 'path';
|
||||
import postcssrc from 'postcss-load-config';
|
||||
import { BUNDLED_THEMES } from 'shiki';
|
||||
import * as tsr from 'tsconfig-resolver';
|
||||
import { fileURLToPath, pathToFileURL } from 'url';
|
||||
import * as vite from 'vite';
|
||||
import { mergeConfig as mergeViteConfig } from 'vite';
|
||||
|
@ -345,11 +346,14 @@ export async function validateConfig(
|
|||
.optional()
|
||||
.default({}),
|
||||
});
|
||||
const tsconfig = loadTSConfig(root);
|
||||
// First-Pass Validation
|
||||
const result = {
|
||||
...(await AstroConfigRelativeSchema.parseAsync(userConfig)),
|
||||
_ctx: {
|
||||
pageExtensions: ['.astro', '.md', '.html'],
|
||||
tsConfig: tsconfig?.config,
|
||||
tsConfigPath: tsconfig?.path,
|
||||
scripts: [],
|
||||
renderers: [jsxRenderer],
|
||||
injectedRoutes: [],
|
||||
|
@ -550,6 +554,18 @@ async function tryLoadConfig(
|
|||
}
|
||||
}
|
||||
|
||||
function loadTSConfig(
|
||||
cwd: string | undefined
|
||||
): tsr.TsConfigResult | undefined {
|
||||
for(const searchName of ['tsconfig.json', 'jsconfig.json']) {
|
||||
const config = tsr.tsconfigResolverSync({ cwd, searchName });
|
||||
if(config.exists) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to load an `astro.config.mjs` file
|
||||
* @deprecated
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import * as path from 'path';
|
||||
import * as tsr from 'tsconfig-resolver';
|
||||
import * as url from 'url';
|
||||
import type { AstroConfig } from '../@types/astro';
|
||||
|
||||
import type * as vite from 'vite';
|
||||
|
@ -14,33 +12,25 @@ export declare interface Alias {
|
|||
/** Returns a path with its slashes replaced with posix slashes. */
|
||||
const normalize = (pathname: string) => String(pathname).split(path.sep).join(path.posix.sep);
|
||||
|
||||
/** Returns the results of a config file if it exists, otherwise null. */
|
||||
const getExistingConfig = (
|
||||
searchName: string,
|
||||
cwd: string | undefined
|
||||
): tsr.TsConfigResultSuccess | null => {
|
||||
const config = tsr.tsconfigResolverSync({ cwd, searchName });
|
||||
|
||||
return config.exists ? config : null;
|
||||
};
|
||||
|
||||
/** Returns a list of compiled aliases. */
|
||||
const getConfigAlias = (cwd: string | undefined): Alias[] | null => {
|
||||
const getConfigAlias = (astroConfig: AstroConfig): Alias[] | null => {
|
||||
/** Closest tsconfig.json or jsconfig.json */
|
||||
const config = getExistingConfig('tsconfig.json', cwd) || getExistingConfig('jsconfig.json', cwd);
|
||||
const config = astroConfig._ctx.tsConfig;
|
||||
const configPath = astroConfig._ctx.tsConfigPath;
|
||||
|
||||
// if no config was found, return null
|
||||
if (!config) return null;
|
||||
if (!config || !configPath) return null;
|
||||
|
||||
/** Compiler options from tsconfig.json or jsconfig.json. */
|
||||
const compilerOptions = Object(config.config.compilerOptions);
|
||||
const compilerOptions = Object(config.compilerOptions);
|
||||
|
||||
// if no compilerOptions.baseUrl was defined, return null
|
||||
if (!compilerOptions.baseUrl) return null;
|
||||
|
||||
// resolve the base url from the configuration file directory
|
||||
const baseUrl = path.posix.resolve(
|
||||
path.posix.dirname(normalize(config.path).replace(/^\/?/, '/')),
|
||||
path.posix.dirname(normalize(configPath).replace(/^\/?/, '/')),
|
||||
normalize(compilerOptions.baseUrl)
|
||||
);
|
||||
|
||||
|
@ -93,7 +83,7 @@ export default function configAliasVitePlugin({
|
|||
config: AstroConfig;
|
||||
}): vite.PluginOption {
|
||||
/** Aliases from the tsconfig.json or jsconfig.json configuration. */
|
||||
const configAlias = getConfigAlias(astroConfig.root && url.fileURLToPath(astroConfig.root));
|
||||
const configAlias = getConfigAlias(astroConfig);
|
||||
|
||||
// if no config alias was found, bypass this plugin
|
||||
if (!configAlias) return {} as vite.PluginOption;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { TransformResult } from 'rollup';
|
||||
import type { TsConfigJson } from 'tsconfig-resolver';
|
||||
import type { Plugin, ResolvedConfig } from 'vite';
|
||||
import type { AstroConfig, AstroRenderer } from '../@types/astro';
|
||||
import type { LogOptions } from '../core/logger/core.js';
|
||||
|
@ -13,6 +14,10 @@ import { error } from '../core/logger/core.js';
|
|||
import { parseNpmName } from '../core/util.js';
|
||||
import tagExportsPlugin from './tag.js';
|
||||
|
||||
type FixedCompilerOptions = TsConfigJson.CompilerOptions & {
|
||||
jsxImportSource?: string;
|
||||
}
|
||||
|
||||
const JSX_EXTENSIONS = new Set(['.jsx', '.tsx', '.mdx']);
|
||||
const IMPORT_STATEMENTS: Record<string, string> = {
|
||||
react: "import React from 'react'",
|
||||
|
@ -223,6 +228,12 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
|
|||
importSource = await detectImportSourceFromImports(code, id, jsxRenderers);
|
||||
}
|
||||
|
||||
// Check the tsconfig
|
||||
if(!importSource) {
|
||||
const compilerOptions = config._ctx.tsConfig?.compilerOptions;
|
||||
importSource = (compilerOptions as FixedCompilerOptions | undefined)?.jsxImportSource;
|
||||
}
|
||||
|
||||
// if we still can’t tell the import source, now is the time to throw an error.
|
||||
if (!importSource && defaultJSXRendererEntry) {
|
||||
const [defaultRendererName] = defaultJSXRendererEntry;
|
||||
|
|
7
packages/astro/test/fixtures/react-and-solid/astro.config.mjs
vendored
Normal file
7
packages/astro/test/fixtures/react-and-solid/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import react from '@astrojs/react';
|
||||
import solid from '@astrojs/solid-js';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [react(), solid()]
|
||||
});
|
8
packages/astro/test/fixtures/react-and-solid/package.json
vendored
Normal file
8
packages/astro/test/fixtures/react-and-solid/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "@test/react-and-solid",
|
||||
"dependencies": {
|
||||
"astro": "workspace:*",
|
||||
"@astrojs/react": "workspace:*",
|
||||
"@astrojs/solid-js": "workspace:*"
|
||||
}
|
||||
}
|
6
packages/astro/test/fixtures/react-and-solid/src/components/ExampleReact.tsx
vendored
Normal file
6
packages/astro/test/fixtures/react-and-solid/src/components/ExampleReact.tsx
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/** @jsxImportSource react */
|
||||
import { FC } from 'react';
|
||||
|
||||
export const ExampleReact: FC = () => {
|
||||
return <div id="example-react">example react component</div>;
|
||||
};
|
5
packages/astro/test/fixtures/react-and-solid/src/components/ExampleSolid.tsx
vendored
Normal file
5
packages/astro/test/fixtures/react-and-solid/src/components/ExampleSolid.tsx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { VoidComponent } from 'solid-js';
|
||||
|
||||
export const ExampleSolid: VoidComponent = () => {
|
||||
return <div id="example-solid">example solidjs component</div>;
|
||||
};
|
13
packages/astro/test/fixtures/react-and-solid/src/pages/index.astro
vendored
Normal file
13
packages/astro/test/fixtures/react-and-solid/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import { ExampleReact } from '../components/ExampleReact';
|
||||
import { ExampleSolid } from '../components/ExampleSolid';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<title>title</title>
|
||||
</head>
|
||||
<body>
|
||||
<ExampleReact />
|
||||
<ExampleSolid />
|
||||
</body>
|
||||
</html>
|
7
packages/astro/test/fixtures/react-and-solid/tsconfig.json
vendored
Normal file
7
packages/astro/test/fixtures/react-and-solid/tsconfig.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"jsxImportSource": "solid-js",
|
||||
"types": ["astro/client"]
|
||||
}
|
||||
}
|
20
packages/astro/test/react-and-solid.test.js
Normal file
20
packages/astro/test/react-and-solid.test.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { expect } from 'chai';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('Solid app with some React components', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({ root: './fixtures/react-and-solid/' });
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Reads jsxImportSource from tsconfig', async () => {
|
||||
let html = await fixture.readFile('/index.html');
|
||||
let $ = cheerio.load(html);
|
||||
expect($('#example-solid').text()).to.equal('example solidjs component');
|
||||
expect($('#example-react').text()).to.equal('example react component');
|
||||
});
|
||||
});
|
|
@ -1748,6 +1748,16 @@ importers:
|
|||
dependencies:
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/react-and-solid:
|
||||
specifiers:
|
||||
'@astrojs/react': workspace:*
|
||||
'@astrojs/solid-js': workspace:*
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
'@astrojs/react': link:../../../../integrations/react
|
||||
'@astrojs/solid-js': link:../../../../integrations/solid
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/react-component:
|
||||
specifiers:
|
||||
'@astrojs/react': workspace:*
|
||||
|
|
Loading…
Reference in a new issue