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: