0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Use acorn to postprocess Astro globs (#5652)

This commit is contained in:
Bjorn Lu 2022-12-21 11:05:18 +08:00 committed by GitHub
parent 7a575d78c2
commit 0b50987584
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 57 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Use acorn to postprocess Astro globs

View file

@ -3,9 +3,7 @@ import { useState } from 'react';
interface Props { interface Props {
obj: BigNestedObject; obj: BigNestedObject;
// TODO: support BigInt in `astro:postprocess` num: bigint;
// num: bigint;
num: number;
arr: any[]; arr: any[];
map: Map<string, string>; map: Map<string, string>;
set: Set<string>; set: Set<string>;

View file

@ -30,8 +30,7 @@ set.add('test2');
</head> </head>
<body> <body>
<main> <main>
<!-- TODO: support BigInt in `astro:postprocess` --> <Component client:load obj={obj} num={11n} arr={[0, "foo"]} map={map} set={set} />
<Component client:load obj={obj} num={11} arr={[0, "foo"]} map={map} set={set} />
</main> </main>
</body> </body>
</html> </html>

View file

@ -32,8 +32,7 @@ test.describe('Passing JS into client components', () => {
await expect(regExpValue).toHaveText('ok'); await expect(regExpValue).toHaveText('ok');
}); });
// TODO: support BigInt in `astro:postprocess` test('BigInts', async ({ page }) => {
test.skip('BigInts', async ({ page }) => {
await page.goto('/'); await page.goto('/');
const bigIntType = await page.locator('#bigint-type'); const bigIntType = await page.locator('#bigint-type');

View file

@ -124,6 +124,7 @@
"@types/babel__core": "^7.1.19", "@types/babel__core": "^7.1.19",
"@types/html-escaper": "^3.0.0", "@types/html-escaper": "^3.0.0",
"@types/yargs-parser": "^21.0.0", "@types/yargs-parser": "^21.0.0",
"acorn": "^8.8.1",
"boxen": "^6.2.1", "boxen": "^6.2.1",
"ci-info": "^3.3.1", "ci-info": "^3.3.1",
"common-ancestor-path": "^1.0.1", "common-ancestor-path": "^1.0.1",
@ -133,6 +134,7 @@
"devalue": "^4.2.0", "devalue": "^4.2.0",
"diff": "^5.1.0", "diff": "^5.1.0",
"es-module-lexer": "^1.1.0", "es-module-lexer": "^1.1.0",
"estree-walker": "^3.0.1",
"execa": "^6.1.0", "execa": "^6.1.0",
"fast-glob": "^3.2.11", "fast-glob": "^3.2.11",
"github-slugger": "^1.4.0", "github-slugger": "^1.4.0",
@ -192,7 +194,6 @@
"@types/rimraf": "^3.0.2", "@types/rimraf": "^3.0.2",
"@types/send": "^0.17.1", "@types/send": "^0.17.1",
"@types/unist": "^2.0.6", "@types/unist": "^2.0.6",
"ast-types": "^0.14.2",
"astro-scripts": "workspace:*", "astro-scripts": "workspace:*",
"chai": "^4.3.6", "chai": "^4.3.6",
"cheerio": "^1.0.0-rc.11", "cheerio": "^1.0.0-rc.11",

View file

@ -1,7 +1,6 @@
import { parse as babelParser } from '@babel/parser'; import { parse } from 'acorn';
import type { ArrowFunctionExpressionKind, CallExpressionKind } from 'ast-types/gen/kinds'; import { walk } from 'estree-walker';
import type { NodePath } from 'ast-types/lib/node-path'; import MagicString from 'magic-string';
import { parse, print, types, visit } from 'recast';
import type { Plugin } from 'vite'; import type { Plugin } from 'vite';
import type { AstroSettings } from '../@types/astro'; import type { AstroSettings } from '../@types/astro';
import { isMarkdownFile } from '../core/util.js'; import { isMarkdownFile } from '../core/util.js';
@ -28,57 +27,48 @@ export default function astro(_opts: AstroPluginOptions): Plugin {
return null; return null;
} }
let s: MagicString | undefined;
const ast = parse(code, { const ast = parse(code, {
// We need to use the babel parser because `import.meta.hot` is not ecmaVersion: 'latest',
// supported by esprima (default parser). In the future, we should sourceType: 'module',
// experiment with other parsers if Babel is too slow or heavy.
parser: { parse: babelParser },
}); });
walk(ast, {
visit(ast, { enter(node: any) {
visitCallExpression: function (path) { // Transform `Astro.glob("./pages/*.astro")` to `Astro.glob(import.meta.glob("./pages/*.astro"), () => "./pages/*.astro")`
// Filter out anything that isn't `Astro.glob()` or `Astro2.glob()` // Also handle for `Astro2.glob()`
if ( if (
!types.namedTypes.MemberExpression.check(path.node.callee) || node.type === 'CallExpression' &&
!types.namedTypes.Identifier.check(path.node.callee.property) || node.callee.type === 'MemberExpression' &&
!(path.node.callee.property.name === 'glob') || node.callee.property.name === 'glob' &&
!types.namedTypes.Identifier.check(path.node.callee.object) || (node.callee.object.name === 'Astro' || node.callee.object.name === 'Astro2') &&
!(path.node.callee.object.name === 'Astro' || path.node.callee.object.name === 'Astro2') node.arguments.length
) { ) {
this.traverse(path); const firstArgStart = node.arguments[0].start;
return; const firstArgEnd = node.arguments[0].end;
const lastArgEnd = node.arguments[node.arguments.length - 1].end;
let firstArg = code.slice(firstArgStart, firstArgEnd);
// If argument is template literal, try convert to a normal string.
// This is needed for compat with previous recast strategy.
// TODO: Remove in Astro 2.0
if (firstArg.startsWith('`') && firstArg.endsWith('`') && !firstArg.includes('${')) {
firstArg = JSON.stringify(firstArg.slice(1, -1));
}
s ??= new MagicString(code);
s.overwrite(
firstArgStart,
lastArgEnd,
`import.meta.glob(${firstArg}), () => ${firstArg}`
);
} }
// Wrap the `Astro.glob()` argument with `import.meta.glob`.
const argsPath = path.get('arguments', 0) as NodePath;
const args = argsPath.value;
argsPath.replace(
{
type: 'CallExpression',
callee: {
type: 'MemberExpression',
object: {
type: 'MetaProperty',
meta: { type: 'Identifier', name: 'import' },
property: { type: 'Identifier', name: 'meta' },
},
property: { type: 'Identifier', name: 'glob' },
computed: false,
},
arguments: [args],
} as CallExpressionKind,
{
type: 'ArrowFunctionExpression',
body: args,
params: [],
} as ArrowFunctionExpressionKind
);
return false;
}, },
}); });
const result = print(ast); if (s) {
return { code: result.code, map: result.map }; return {
code: s.toString(),
map: s.generateMap(),
};
}
}, },
}; };
} }

View file

@ -422,7 +422,7 @@ importers:
'@types/send': ^0.17.1 '@types/send': ^0.17.1
'@types/unist': ^2.0.6 '@types/unist': ^2.0.6
'@types/yargs-parser': ^21.0.0 '@types/yargs-parser': ^21.0.0
ast-types: ^0.14.2 acorn: ^8.8.1
astro-scripts: workspace:* astro-scripts: workspace:*
boxen: ^6.2.1 boxen: ^6.2.1
chai: ^4.3.6 chai: ^4.3.6
@ -436,6 +436,7 @@ importers:
diff: ^5.1.0 diff: ^5.1.0
eol: ^0.9.1 eol: ^0.9.1
es-module-lexer: ^1.1.0 es-module-lexer: ^1.1.0
estree-walker: ^3.0.1
execa: ^6.1.0 execa: ^6.1.0
fast-glob: ^3.2.11 fast-glob: ^3.2.11
github-slugger: ^1.4.0 github-slugger: ^1.4.0
@ -500,6 +501,7 @@ importers:
'@types/babel__core': 7.1.20 '@types/babel__core': 7.1.20
'@types/html-escaper': 3.0.0 '@types/html-escaper': 3.0.0
'@types/yargs-parser': 21.0.0 '@types/yargs-parser': 21.0.0
acorn: 8.8.1
boxen: 6.2.1 boxen: 6.2.1
ci-info: 3.6.1 ci-info: 3.6.1
common-ancestor-path: 1.0.1 common-ancestor-path: 1.0.1
@ -509,6 +511,7 @@ importers:
devalue: 4.2.0 devalue: 4.2.0
diff: 5.1.0 diff: 5.1.0
es-module-lexer: 1.1.0 es-module-lexer: 1.1.0
estree-walker: 3.0.1
execa: 6.1.0 execa: 6.1.0
fast-glob: 3.2.12 fast-glob: 3.2.12
github-slugger: 1.5.0 github-slugger: 1.5.0
@ -567,7 +570,6 @@ importers:
'@types/rimraf': 3.0.2 '@types/rimraf': 3.0.2
'@types/send': 0.17.1 '@types/send': 0.17.1
'@types/unist': 2.0.6 '@types/unist': 2.0.6
ast-types: 0.14.2
astro-scripts: link:../../scripts astro-scripts: link:../../scripts
chai: 4.3.7 chai: 4.3.7
cheerio: 1.0.0-rc.12 cheerio: 1.0.0-rc.12
@ -10703,6 +10705,7 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
tslib: 2.4.1 tslib: 2.4.1
dev: false
/astring/1.8.3: /astring/1.8.3:
resolution: {integrity: sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==} resolution: {integrity: sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==}