diff --git a/.changeset/neat-seas-peel.md b/.changeset/neat-seas-peel.md new file mode 100644 index 000000000..71ce868cc --- /dev/null +++ b/.changeset/neat-seas-peel.md @@ -0,0 +1,23 @@ +--- +'astro': patch +--- + +Allow TypeScript inside script tags + +This makes it so that you can use TypeScript inside of script tags like so: + +```html + +``` + +Note that the the VSCode extension does not currently support this, however. diff --git a/packages/astro/src/core/build/vite-plugin-analyzer.ts b/packages/astro/src/core/build/vite-plugin-analyzer.ts index 04b439b69..8b9950ff1 100644 --- a/packages/astro/src/core/build/vite-plugin-analyzer.ts +++ b/packages/astro/src/core/build/vite-plugin-analyzer.ts @@ -21,7 +21,7 @@ export function vitePluginAnalyzer( scan(this: PluginContext, scripts: AstroPluginMetadata['astro']['scripts'], from: string) { const hoistedScripts = new Set(); for (let i = 0; i < scripts.length; i++) { - const hid = `${from.replace('/@fs', '')}?astro&type=script&index=${i}`; + const hid = `${from.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`; hoistedScripts.add(hid); } diff --git a/packages/astro/src/runtime/server/metadata.ts b/packages/astro/src/runtime/server/metadata.ts index c736820d2..3093ee7f1 100644 --- a/packages/astro/src/runtime/server/metadata.ts +++ b/packages/astro/src/runtime/server/metadata.ts @@ -65,7 +65,7 @@ export class Metadata { while (i < metadata.hoisted.length) { // Strip off the leading "/@fs" added during compilation. - yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}`; + yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`; i++; } } diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index 94fea7c89..cca58834e 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -15,7 +15,7 @@ import { PAGE_SCRIPT_ID, PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index import { getFileInfo } from '../vite-plugin-utils/index.js'; import { cachedCompilation, CompileProps } from './compile.js'; import { handleHotUpdate, trackCSSDependencies } from './hmr.js'; -import { parseAstroRequest } from './query.js'; +import { parseAstroRequest, ParsedRequestResult } from './query.js'; import { getViteTransform, TransformHook } from './styles.js'; const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms; @@ -48,6 +48,16 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu const srcRootWeb = config.srcDir.pathname.slice(config.root.pathname.length - 1); const isBrowserPath = (path: string) => path.startsWith(srcRootWeb); + function resolveRelativeFromAstroParent(id: string, parsedFrom: ParsedRequestResult): string { + const filename = normalizeFilename(parsedFrom.filename); + const resolvedURL = new URL(id, `file://${filename}`); + const resolved = resolvedURL.pathname; + if (isBrowserPath(resolved)) { + return relativeToRoot(resolved + resolvedURL.search); + } + return slash(fileURLToPath(resolvedURL)) + resolvedURL.search; + } + return { name: 'astro:build', enforce: 'pre', // run transforms before other plugins can @@ -59,19 +69,17 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu viteDevServer = server; }, // note: don’t claim .astro files with resolveId() — it prevents Vite from transpiling the final JS (import.meta.globEager, etc.) - async resolveId(id, from) { + async resolveId(id, from, opts) { // If resolving from an astro subresource such as a hoisted script, // we need to resolve relative paths ourselves. if (from) { const parsedFrom = parseAstroRequest(from); - if (parsedFrom.query.astro && isRelativePath(id) && parsedFrom.query.type === 'script') { - const filename = normalizeFilename(parsedFrom.filename); - const resolvedURL = new URL(id, `file://${filename}`); - const resolved = resolvedURL.pathname; - if (isBrowserPath(resolved)) { - return relativeToRoot(resolved + resolvedURL.search); - } - return slash(fileURLToPath(resolvedURL)) + resolvedURL.search; + const isAstroScript = parsedFrom.query.astro && parsedFrom.query.type === 'script'; + if (isAstroScript && isRelativePath(id)) { + return this.resolve(resolveRelativeFromAstroParent(id, parsedFrom), from, { + custom: opts.custom, + skipSelf: true, + }); } } @@ -170,6 +178,11 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu hoistedScript.type === 'inline' ? hoistedScript.code! : `import "${hoistedScript.src!}";`, + meta: { + vite: { + lang: 'ts', + }, + } }; } } @@ -205,8 +218,8 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu let i = 0; while (i < transformResult.scripts.length) { - deps.add(`${id}?astro&type=script&index=${i}`); - SUFFIX += `import "${id}?astro&type=script&index=${i}";`; + deps.add(`${id}?astro&type=script&index=${i}&lang.ts`); + SUFFIX += `import "${id}?astro&type=script&index=${i}&lang.ts";`; i++; } diff --git a/packages/astro/src/vite-plugin-astro/query.ts b/packages/astro/src/vite-plugin-astro/query.ts index ae923c153..e6eff13d7 100644 --- a/packages/astro/src/vite-plugin-astro/query.ts +++ b/packages/astro/src/vite-plugin-astro/query.ts @@ -7,13 +7,15 @@ export interface AstroQuery { raw?: boolean; } +export interface ParsedRequestResult { + filename: string; + query: AstroQuery; +}; + // Parses an id to check if its an Astro request. // CSS is imported like `import '/src/pages/index.astro?astro&type=style&index=0&lang.css'; // This parses those ids and returns an object representing what it found. -export function parseAstroRequest(id: string): { - filename: string; - query: AstroQuery; -} { +export function parseAstroRequest(id: string): ParsedRequestResult { const [filename, rawQuery] = id.split(`?`, 2); const query = Object.fromEntries(new URLSearchParams(rawQuery).entries()) as AstroQuery; if (query.astro != null) { diff --git a/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro b/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro index dfe895d6c..13c64eb37 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro @@ -1,3 +1,11 @@ diff --git a/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts new file mode 100644 index 000000000..6125b5a48 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts @@ -0,0 +1 @@ +console.log('some-files/one'); diff --git a/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts new file mode 100644 index 000000000..113f7075f --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts @@ -0,0 +1 @@ +console.log('some-files/two'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7224fe7fc..05c6e0f56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8258,6 +8258,11 @@ packages: /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.3 dev: false @@ -11179,6 +11184,8 @@ packages: debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.2.4 + transitivePeerDependencies: + - supports-color dev: false /netmask/2.0.2: @@ -11262,6 +11269,8 @@ packages: rimraf: 2.7.1 semver: 5.7.1 tar: 4.4.19 + transitivePeerDependencies: + - supports-color dev: false /node-releases/2.0.5: