Allow TypeScript in hoisted scripts (#3665)
* Allow TypeScript in hoisted scripts * Pass skipSelf * Fix linting
This commit is contained in:
parent
c2dffc1c38
commit
9a813268db
9 changed files with 76 additions and 19 deletions
23
.changeset/neat-seas-peel.md
Normal file
23
.changeset/neat-seas-peel.md
Normal file
|
@ -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
|
||||
<script>
|
||||
interface Person {
|
||||
name: string;
|
||||
}
|
||||
|
||||
const person: Person = {
|
||||
name: 'Astro'
|
||||
};
|
||||
|
||||
console.log(person);
|
||||
</script>
|
||||
```
|
||||
|
||||
Note that the the VSCode extension does not currently support this, however.
|
|
@ -21,7 +21,7 @@ export function vitePluginAnalyzer(
|
|||
scan(this: PluginContext, scripts: AstroPluginMetadata['astro']['scripts'], from: string) {
|
||||
const hoistedScripts = new Set<string>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
<script>
|
||||
console.log('some content here.');
|
||||
import '../scripts/some-files/one';
|
||||
import '../scripts/some-files/two.js';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
}
|
||||
const props: Props = { name: 'some string' };
|
||||
|
||||
console.log('some content here.', props);
|
||||
</script>
|
||||
|
|
1
packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts
vendored
Normal file
1
packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log('some-files/one');
|
1
packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts
vendored
Normal file
1
packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log('some-files/two');
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue