mirror of
https://github.com/withastro/astro.git
synced 2025-02-17 22:44:24 -05:00
add typescript support for expressions
This commit is contained in:
parent
f28590e640
commit
d125d57b3a
6 changed files with 58 additions and 29 deletions
|
@ -49,7 +49,7 @@
|
||||||
working on!</div>
|
working on!</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{context.news.reverse().map((item) =>
|
{context.news.reverse().map((item: any) =>
|
||||||
<Card:dynamic item={item} />)}
|
<Card:dynamic item={item} />)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -67,9 +67,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/parser": {
|
"@babel/parser": {
|
||||||
"version": "7.13.10",
|
"version": "7.13.11",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.10.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.11.tgz",
|
||||||
"integrity": "sha512-0s7Mlrw9uTWkYua7xWr99Wpk2bnGa0ANleKfksYAES8LpWH4gW1OUr42vqKNf0us5UQNfru2wPqMqRITzq/SIQ=="
|
"integrity": "sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q=="
|
||||||
},
|
},
|
||||||
"@babel/types": {
|
"@babel/types": {
|
||||||
"version": "7.13.0",
|
"version": "7.13.0",
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
"yargs-parser": "^20.2.7"
|
"yargs-parser": "^20.2.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/parser": "^7.13.11",
|
||||||
"@types/github-slugger": "^1.3.0",
|
"@types/github-slugger": "^1.3.0",
|
||||||
"@types/sass": "^1.16.0",
|
"@types/sass": "^1.16.0",
|
||||||
"@types/yargs-parser": "^20.2.0",
|
"@types/yargs-parser": "^20.2.0",
|
||||||
|
|
|
@ -146,8 +146,8 @@ function getComponentWrapper(_name: string, { type, url }: { type: string; url:
|
||||||
throw new Error('Unknown Component Type: ' + name);
|
throw new Error('Unknown Component Type: ' + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileScriptSafe(raw: string, loader: 'jsx' | 'tsx'): string {
|
function compileScriptSafe(raw: string): string {
|
||||||
let compiledCode = compileExpressionSafe(raw, loader);
|
let compiledCode = compileExpressionSafe(raw);
|
||||||
// esbuild treeshakes unused imports. In our case these are components, so let's keep them.
|
// esbuild treeshakes unused imports. In our case these are components, so let's keep them.
|
||||||
const imports = eslexer
|
const imports = eslexer
|
||||||
.parse(raw)[0]
|
.parse(raw)[0]
|
||||||
|
@ -161,9 +161,9 @@ function compileScriptSafe(raw: string, loader: 'jsx' | 'tsx'): string {
|
||||||
return compiledCode;
|
return compiledCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileExpressionSafe(raw: string, loader: 'jsx' | 'tsx'): string {
|
function compileExpressionSafe(raw: string): string {
|
||||||
let { code } = transformSync(raw, {
|
let { code } = transformSync(raw, {
|
||||||
loader,
|
loader: 'tsx',
|
||||||
jsxFactory: 'h',
|
jsxFactory: 'h',
|
||||||
jsxFragment: 'Fragment',
|
jsxFragment: 'Fragment',
|
||||||
charset: 'utf8',
|
charset: 'utf8',
|
||||||
|
@ -175,7 +175,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
|
||||||
await eslexer.init;
|
await eslexer.init;
|
||||||
|
|
||||||
// Compile scripts as TypeScript, always
|
// Compile scripts as TypeScript, always
|
||||||
const script = compileScriptSafe(ast.module ? ast.module.content : '', 'tsx');
|
const script = compileScriptSafe(ast.module ? ast.module.content : '');
|
||||||
|
|
||||||
// Todo: Validate that `h` and `Fragment` aren't defined in the script
|
// Todo: Validate that `h` and `Fragment` aren't defined in the script
|
||||||
const [scriptImports] = eslexer.parse(script, 'optional-sourcename');
|
const [scriptImports] = eslexer.parse(script, 'optional-sourcename');
|
||||||
|
@ -198,7 +198,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
|
||||||
enter(node: TemplateNode) {
|
enter(node: TemplateNode) {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'MustacheTag':
|
case 'MustacheTag':
|
||||||
let code = compileExpressionSafe(node.expression, 'jsx');
|
let code = compileExpressionSafe(node.expression);
|
||||||
|
|
||||||
let matches: RegExpExecArray[] = [];
|
let matches: RegExpExecArray[] = [];
|
||||||
let match: RegExpExecArray | null | undefined;
|
let match: RegExpExecArray | null | undefined;
|
||||||
|
|
|
@ -1,20 +1,49 @@
|
||||||
import { Node } from 'acorn';
|
import type { Node } from 'acorn';
|
||||||
import acorn from 'acorn';
|
import { parseExpression } from '@babel/parser';
|
||||||
// @ts-ignore
|
// import acorn from 'acorn';
|
||||||
import jsx from 'acorn-jsx';
|
// // @ts-ignore
|
||||||
|
// import jsx from 'acorn-jsx';
|
||||||
|
// const acornJsx = acorn.Parser.extend(jsx());
|
||||||
|
|
||||||
const acornJsx = acorn.Parser.extend(jsx());
|
export const parse = (source: string): Node => {
|
||||||
|
throw new Error('No longer used.');
|
||||||
|
// acorn.parse(source, {
|
||||||
|
// sourceType: 'module',
|
||||||
|
// ecmaVersion: 2020,
|
||||||
|
// locations: true,
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
export const parse = (source: string): Node =>
|
export const parse_expression_at = (source: string, index: number) => {
|
||||||
acorn.parse(source, {
|
// TODO: Clean up after acorn -> @babel/parser move
|
||||||
sourceType: 'module',
|
try {
|
||||||
ecmaVersion: 2020,
|
parseExpression(source.slice(index), {
|
||||||
locations: true,
|
sourceType: 'module',
|
||||||
});
|
plugins: ['jsx', 'typescript'],
|
||||||
|
});
|
||||||
export const parse_expression_at = (source: string, index: number): Node =>
|
throw new Error('Parse error.'); // Expected to fail.
|
||||||
acornJsx.parseExpressionAt(source, index, {
|
} catch (err) {
|
||||||
sourceType: 'module',
|
if (!err.pos) {
|
||||||
ecmaVersion: 2020,
|
throw err;
|
||||||
locations: true,
|
}
|
||||||
});
|
try {
|
||||||
|
const result = parseExpression(source.slice(index, index + err.pos), {
|
||||||
|
sourceType: 'module',
|
||||||
|
plugins: ['jsx', 'typescript'],
|
||||||
|
});
|
||||||
|
result.start = index;
|
||||||
|
result.end = index + err.pos;
|
||||||
|
return result;
|
||||||
|
} catch (err2) {
|
||||||
|
if (err2.pos) {
|
||||||
|
err2.pos = index + err2.pos;
|
||||||
|
}
|
||||||
|
throw err2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// acornJsx.parseExpressionAt(source, index, {
|
||||||
|
// sourceType: 'module',
|
||||||
|
// ecmaVersion: 2020,
|
||||||
|
// locations: true,
|
||||||
|
// });
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { whitespace } from '../../utils/patterns.js';
|
||||||
export default function read_expression(parser: Parser): string {
|
export default function read_expression(parser: Parser): string {
|
||||||
try {
|
try {
|
||||||
const node = parse_expression_at(parser.template, parser.index);
|
const node = parse_expression_at(parser.template, parser.index);
|
||||||
|
|
||||||
let num_parens = 0;
|
let num_parens = 0;
|
||||||
|
|
||||||
for (let i = parser.index; i < node.start; i += 1) {
|
for (let i = parser.index; i < node.start; i += 1) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue