add typescript support for expressions

This commit is contained in:
Fred K. Schott 2021-03-22 00:26:59 -07:00
parent f28590e640
commit d125d57b3a
6 changed files with 58 additions and 29 deletions

View file

@ -49,7 +49,7 @@
working on!</div>
</article>
{context.news.reverse().map((item) =>
{context.news.reverse().map((item: any) =>
<Card:dynamic item={item} />)}
</div>

6
package-lock.json generated
View file

@ -67,9 +67,9 @@
}
},
"@babel/parser": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.10.tgz",
"integrity": "sha512-0s7Mlrw9uTWkYua7xWr99Wpk2bnGa0ANleKfksYAES8LpWH4gW1OUr42vqKNf0us5UQNfru2wPqMqRITzq/SIQ=="
"version": "7.13.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.11.tgz",
"integrity": "sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q=="
},
"@babel/types": {
"version": "7.13.0",

View file

@ -56,6 +56,7 @@
"yargs-parser": "^20.2.7"
},
"devDependencies": {
"@babel/parser": "^7.13.11",
"@types/github-slugger": "^1.3.0",
"@types/sass": "^1.16.0",
"@types/yargs-parser": "^20.2.0",

View file

@ -146,8 +146,8 @@ function getComponentWrapper(_name: string, { type, url }: { type: string; url:
throw new Error('Unknown Component Type: ' + name);
}
function compileScriptSafe(raw: string, loader: 'jsx' | 'tsx'): string {
let compiledCode = compileExpressionSafe(raw, loader);
function compileScriptSafe(raw: string): string {
let compiledCode = compileExpressionSafe(raw);
// esbuild treeshakes unused imports. In our case these are components, so let's keep them.
const imports = eslexer
.parse(raw)[0]
@ -161,9 +161,9 @@ function compileScriptSafe(raw: string, loader: 'jsx' | 'tsx'): string {
return compiledCode;
}
function compileExpressionSafe(raw: string, loader: 'jsx' | 'tsx'): string {
function compileExpressionSafe(raw: string): string {
let { code } = transformSync(raw, {
loader,
loader: 'tsx',
jsxFactory: 'h',
jsxFragment: 'Fragment',
charset: 'utf8',
@ -175,7 +175,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
await eslexer.init;
// 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
const [scriptImports] = eslexer.parse(script, 'optional-sourcename');
@ -198,7 +198,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
enter(node: TemplateNode) {
switch (node.type) {
case 'MustacheTag':
let code = compileExpressionSafe(node.expression, 'jsx');
let code = compileExpressionSafe(node.expression);
let matches: RegExpExecArray[] = [];
let match: RegExpExecArray | null | undefined;

View file

@ -1,20 +1,49 @@
import { Node } from 'acorn';
import acorn from 'acorn';
// @ts-ignore
import jsx from 'acorn-jsx';
import type { Node } from 'acorn';
import { parseExpression } from '@babel/parser';
// import acorn from 'acorn';
// // @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 =>
acorn.parse(source, {
sourceType: 'module',
ecmaVersion: 2020,
locations: true,
});
export const parse_expression_at = (source: string, index: number): Node =>
acornJsx.parseExpressionAt(source, index, {
sourceType: 'module',
ecmaVersion: 2020,
locations: true,
});
export const parse_expression_at = (source: string, index: number) => {
// TODO: Clean up after acorn -> @babel/parser move
try {
parseExpression(source.slice(index), {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
});
throw new Error('Parse error.'); // Expected to fail.
} catch (err) {
if (!err.pos) {
throw err;
}
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,
// });

View file

@ -8,7 +8,6 @@ import { whitespace } from '../../utils/patterns.js';
export default function read_expression(parser: Parser): string {
try {
const node = parse_expression_at(parser.template, parser.index);
let num_parens = 0;
for (let i = parser.index; i < node.start; i += 1) {