summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fred K. Schott <fkschott@gmail.com> 2021-03-25 00:00:22 -0700
committerGravatar GitHub <noreply@github.com> 2021-03-25 00:00:22 -0700
commit30cccdf7154b6470e876464da9e412af10894dd5 (patch)
tree73ed40b30af23ba3e5b94070e478f3e2ca1670c0 /src
parenta72ab10c623022860691d6a095b74dea70cc6f69 (diff)
downloadastro-30cccdf7154b6470e876464da9e412af10894dd5.tar.gz
astro-30cccdf7154b6470e876464da9e412af10894dd5.tar.zst
astro-30cccdf7154b6470e876464da9e412af10894dd5.zip
add component state, top-level await support (#26)
Diffstat (limited to 'src')
-rw-r--r--src/@types/astro.ts2
-rw-r--r--src/@types/optimizer.ts2
-rw-r--r--src/compiler/codegen.ts (renamed from src/codegen/index.ts)105
-rw-r--r--src/compiler/index.ts172
-rw-r--r--src/compiler/optimize/index.ts (renamed from src/optimize/index.ts)4
-rw-r--r--src/compiler/optimize/styles.ts (renamed from src/optimize/styles.ts)4
-rw-r--r--src/logger.ts2
-rw-r--r--src/micromark-collect-headers.ts1
-rw-r--r--src/parser/README.md (renamed from src/compiler/README.md)0
-rw-r--r--src/parser/Stats.ts (renamed from src/compiler/Stats.ts)0
-rw-r--r--src/parser/config.ts (renamed from src/compiler/config.ts)0
-rw-r--r--src/parser/index.ts1
-rw-r--r--src/parser/interfaces.ts (renamed from src/compiler/interfaces.ts)6
-rw-r--r--src/parser/parse/acorn.ts (renamed from src/compiler/parse/acorn.ts)2
-rw-r--r--src/parser/parse/index.ts (renamed from src/compiler/parse/index.ts)0
-rw-r--r--src/parser/parse/read/context.ts (renamed from src/compiler/parse/read/context.ts)0
-rw-r--r--src/parser/parse/read/expression.ts (renamed from src/compiler/parse/read/expression.ts)2
-rw-r--r--src/parser/parse/read/script.ts (renamed from src/compiler/parse/read/script.ts)0
-rw-r--r--src/parser/parse/read/style.ts (renamed from src/compiler/parse/read/style.ts)0
-rw-r--r--src/parser/parse/state/fragment.ts (renamed from src/compiler/parse/state/fragment.ts)0
-rw-r--r--src/parser/parse/state/mustache.ts (renamed from src/compiler/parse/state/mustache.ts)4
-rw-r--r--src/parser/parse/state/setup.ts (renamed from src/compiler/parse/state/setup.ts)0
-rw-r--r--src/parser/parse/state/tag.ts (renamed from src/compiler/parse/state/tag.ts)6
-rw-r--r--src/parser/parse/state/text.ts (renamed from src/compiler/parse/state/text.ts)0
-rw-r--r--src/parser/parse/utils/bracket.ts (renamed from src/compiler/parse/utils/bracket.ts)0
-rw-r--r--src/parser/parse/utils/entities.ts (renamed from src/compiler/parse/utils/entities.ts)0
-rw-r--r--src/parser/parse/utils/html.ts (renamed from src/compiler/parse/utils/html.ts)0
-rw-r--r--src/parser/parse/utils/node.ts (renamed from src/compiler/parse/utils/node.ts)0
-rw-r--r--src/parser/utils/error.ts (renamed from src/compiler/utils/error.ts)0
-rw-r--r--src/parser/utils/full_char_code_at.ts (renamed from src/compiler/utils/full_char_code_at.ts)0
-rw-r--r--src/parser/utils/fuzzymatch.ts (renamed from src/compiler/utils/fuzzymatch.ts)0
-rw-r--r--src/parser/utils/get_code_frame.ts (renamed from src/compiler/utils/get_code_frame.ts)0
-rw-r--r--src/parser/utils/link.ts (renamed from src/compiler/utils/link.ts)0
-rw-r--r--src/parser/utils/list.ts (renamed from src/compiler/utils/list.ts)0
-rw-r--r--src/parser/utils/names.ts (renamed from src/compiler/utils/names.ts)0
-rw-r--r--src/parser/utils/namespaces.ts (renamed from src/compiler/utils/namespaces.ts)0
-rw-r--r--src/parser/utils/nodes_match.ts (renamed from src/compiler/utils/nodes_match.ts)0
-rw-r--r--src/parser/utils/patterns.ts (renamed from src/compiler/utils/patterns.ts)0
-rw-r--r--src/parser/utils/trim.ts (renamed from src/compiler/utils/trim.ts)0
-rw-r--r--src/runtime.ts2
-rw-r--r--src/transform2.ts172
41 files changed, 266 insertions, 221 deletions
diff --git a/src/@types/astro.ts b/src/@types/astro.ts
index 8a92983f8..d0f9242c9 100644
--- a/src/@types/astro.ts
+++ b/src/@types/astro.ts
@@ -21,7 +21,7 @@ export interface JsxItem {
export interface TransformResult {
script: string;
- props: string[];
+ imports: string[];
items: JsxItem[];
}
diff --git a/src/@types/optimizer.ts b/src/@types/optimizer.ts
index c62976068..b9e228f3e 100644
--- a/src/@types/optimizer.ts
+++ b/src/@types/optimizer.ts
@@ -1,4 +1,4 @@
-import type { TemplateNode } from '../compiler/interfaces';
+import type { TemplateNode } from '../parser/interfaces';
export type VisitorFn = (node: TemplateNode) => void;
diff --git a/src/codegen/index.ts b/src/compiler/codegen.ts
index 2eb289887..52249fd77 100644
--- a/src/codegen/index.ts
+++ b/src/compiler/codegen.ts
@@ -1,13 +1,20 @@
import type { CompileOptions } from '../@types/compiler';
import type { ValidExtensionPlugins } from '../@types/astro';
-import type { Ast, TemplateNode } from '../compiler/interfaces';
+import type { Ast, TemplateNode } from '../parser/interfaces';
import type { JsxItem, TransformResult } from '../@types/astro';
import eslexer from 'es-module-lexer';
import esbuild from 'esbuild';
import path from 'path';
import { walk } from 'estree-walker';
+import babelParser from '@babel/parser';
+import _babelGenerator from '@babel/generator';
+import traverse from '@babel/traverse';
+import { ImportDeclaration,ExportNamedDeclaration, VariableDeclarator, Identifier, VariableDeclaration } from '@babel/types';
+const babelGenerator: typeof _babelGenerator =
+ // @ts-ignore
+ _babelGenerator.default;
const { transformSync } = esbuild;
interface Attribute {
@@ -43,8 +50,8 @@ function getAttributes(attrs: Attribute[]): Record<string, string> {
'(' +
attr.value
.map((v: TemplateNode) => {
- if (v.expression) {
- return v.expression;
+ if (v.content) {
+ return v.content;
} else {
return JSON.stringify(getTextFromAttribute(v));
}
@@ -60,7 +67,7 @@ function getAttributes(attrs: Attribute[]): Record<string, string> {
}
switch (val.type) {
case 'MustacheTag':
- result[attr.name] = '(' + val.expression + ')';
+ result[attr.name] = '(' + val.content + ')';
continue;
case 'Text':
result[attr.name] = JSON.stringify(getTextFromAttribute(val));
@@ -211,24 +218,68 @@ function compileExpressionSafe(raw: string): string {
export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Promise<TransformResult> {
await eslexer.init;
- // Compile scripts as TypeScript, always
- const script = compileScriptSafe(ast.module ? ast.module.content : '');
+ const componentImports: ImportDeclaration[] = [];
+ const componentProps: VariableDeclarator[] = [];
+ const componentExports: ExportNamedDeclaration[] = [];
- // Collect all exported variables for props
- const scannedExports = eslexer.parse(script)[1].filter((n) => n !== 'setup' && n !== 'layout');
+ let script = '';
+ let propsStatement: string = '';
+ const importExportStatements: Set<string> = new Set();
+ const components: Record<string, { type: string; url: string }> = {};
- // Todo: Validate that `h` and `Fragment` aren't defined in the script
- const [scriptImports] = eslexer.parse(script, 'optional-sourcename');
- const components = Object.fromEntries(
- scriptImports.map((imp) => {
- const componentType = path.posix.extname(imp.n!);
- const componentName = path.posix.basename(imp.n!, componentType);
- return [componentName, { type: componentType, url: imp.n! }];
- })
- );
+ if (ast.module) {
+ const program = babelParser.parse(ast.module.content, {
+ sourceType: 'module',
+ plugins: ['jsx', 'typescript', 'topLevelAwait'],
+ }).program;
+
+ const { body } = program;
+ let i = body.length;
+ while (--i >= 0) {
+ const node = body[i];
+ if (node.type === 'ImportDeclaration') {
+ componentImports.push(node);
+ body.splice(i, 1);
+ }
+ if (/^Export/.test(node.type)) {
+ if (node.type === 'ExportNamedDeclaration' && node.declaration?.type === 'VariableDeclaration') {
+ const declaration = node.declaration.declarations[0];
+ if ((declaration.id as Identifier).name === '__layout' || (declaration.id as Identifier).name === '__content') {
+ componentExports.push(node);
+ } else {
+ componentProps.push(declaration);
+ }
+ body.splice(i, 1);
+ }
+ // const replacement = extract_exports(node);
+ }
+ }
+
+ for (const componentImport of componentImports) {
+ const importUrl = componentImport.source.value;
+ const componentType = path.posix.extname(importUrl);
+ const componentName = path.posix.basename(importUrl, componentType);
+ components[componentName] = { type: componentType, url: importUrl };
+ importExportStatements.add(ast.module.content.slice(componentImport.start!, componentImport.end!));
+ }
+ for (const componentImport of componentExports) {
+ importExportStatements.add(ast.module.content.slice(componentImport.start!, componentImport.end!));
+ }
+
+ if (componentProps.length > 0) {
+ propsStatement = 'let {';
+ for (const componentExport of componentProps) {
+ propsStatement += `${(componentExport.id as Identifier).name}`;
+ if (componentExport.init) {
+ propsStatement += `= ${babelGenerator(componentExport.init!).code }`;
+ }
+ propsStatement += `,`;
+ }
+ propsStatement += `} = props;`;
+ }
+ script = propsStatement + babelGenerator(program).code;
+ }
- const additionalImports = new Set<string>();
- let headItem: JsxItem | undefined;
let items: JsxItem[] = [];
let collectionItem: JsxItem | undefined;
let currentItemName: string | undefined;
@@ -238,7 +289,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
enter(node: TemplateNode) {
switch (node.type) {
case 'MustacheTag':
- let code = compileExpressionSafe(node.expression);
+ let code = compileExpressionSafe(node.content);
let matches: RegExpExecArray[] = [];
let match: RegExpExecArray | null | undefined;
@@ -255,13 +306,14 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
}
const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], compileOptions);
if (wrapperImport) {
- additionalImports.add(wrapperImport);
+ importExportStatements.add(wrapperImport);
}
if (wrapper !== name) {
code = code.slice(0, match.index + 2) + wrapper + code.slice(match.index + match[0].length - 1);
}
}
collectionItem!.jsx += `,(${code.trim().replace(/\;$/, '')})`;
+ this.skip();
return;
case 'Comment':
return;
@@ -287,11 +339,6 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
currentItemName = name;
if (!collectionItem) {
collectionItem = { name, jsx: '' };
- if (node.type === 'Head') {
- collectionItem.jsx += `h(Fragment, null`;
- headItem = collectionItem;
- return;
- }
items.push(collectionItem);
}
collectionItem.jsx += collectionItem.jsx === '' ? '' : ',';
@@ -311,7 +358,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
}
const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], compileOptions);
if (wrapperImport) {
- additionalImports.add(wrapperImport);
+ importExportStatements.add(wrapperImport);
}
collectionItem.jsx += `h(${wrapper}, ${attributes ? generateAttributes(attributes) : 'null'}`;
@@ -381,8 +428,8 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
});
return {
- script: script + '\n' + Array.from(additionalImports).join('\n'),
+ script: script,
+ imports: Array.from(importExportStatements),
items,
- props: scannedExports,
};
}
diff --git a/src/compiler/index.ts b/src/compiler/index.ts
index 718199c94..e09664a19 100644
--- a/src/compiler/index.ts
+++ b/src/compiler/index.ts
@@ -1 +1,171 @@
-export { default as parse } from './parse/index.js';
+import type { LogOptions } from '../logger.js';
+
+import path from 'path';
+import micromark from 'micromark';
+import gfmSyntax from 'micromark-extension-gfm';
+import matter from 'gray-matter';
+import gfmHtml from 'micromark-extension-gfm/html.js';
+import { CompileResult, TransformResult } from '../@types/astro';
+import { parse } from '../parser/index.js';
+import { createMarkdownHeadersCollector } from '../micromark-collect-headers.js';
+import { encodeMarkdown } from '../micromark-encode.js';
+import { defaultLogOptions } from '../logger.js';
+import { optimize } from './optimize/index.js';
+import { codegen } from './codegen.js';
+
+interface CompileOptions {
+ logging: LogOptions;
+ resolve: (p: string) => string;
+}
+
+const defaultCompileOptions: CompileOptions = {
+ logging: defaultLogOptions,
+ resolve: (p: string) => p,
+};
+
+function internalImport(internalPath: string) {
+ return `/_astro_internal/${internalPath}`;
+}
+
+interface ConvertAstroOptions {
+ compileOptions: CompileOptions;
+ filename: string;
+ fileID: string;
+}
+
+async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): Promise<TransformResult> {
+ const { filename } = opts;
+
+ // 1. Parse
+ const ast = parse(template, {
+ filename,
+ });
+
+ // 2. Optimize the AST
+ await optimize(ast, opts);
+
+ // Turn AST into JSX
+ return await codegen(ast, opts);
+}
+
+async function convertMdToJsx(
+ contents: string,
+ { compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string }
+): Promise<TransformResult> {
+ const { data: frontmatterData, content } = matter(contents);
+ const { headers, headersExtension } = createMarkdownHeadersCollector();
+ const mdHtml = micromark(content, {
+ allowDangerousHtml: true,
+ extensions: [gfmSyntax()],
+ htmlExtensions: [gfmHtml, encodeMarkdown, headersExtension],
+ });
+
+ // TODO: Warn if reserved word is used in "frontmatterData"
+ const contentData: any = {
+ ...frontmatterData,
+ headers,
+ source: content,
+ };
+
+ let imports = '';
+ for (let [ComponentName, specifier] of Object.entries(frontmatterData.import || {})) {
+ imports += `import ${ComponentName} from '${specifier}';\n`;
+ }
+
+ // </script> can't be anywhere inside of a JS string, otherwise the HTML parser fails.
+ // Break it up here so that the HTML parser won't detect it.
+ const stringifiedSetupContext = JSON.stringify(contentData).replace(/\<\/script\>/g, `</scrip" + "t>`);
+
+ const raw = `---
+ ${imports}
+ ${frontmatterData.layout ? `export const __layout = ${JSON.stringify(frontmatterData.layout)};` : ''}
+ export const __content = ${stringifiedSetupContext};
+---
+<section>${mdHtml}</section>`;
+
+ const convertOptions = { compileOptions, filename, fileID };
+
+ return convertAstroToJsx(raw, convertOptions);
+}
+
+type SupportedExtensions = '.astro' | '.md';
+
+async function transformFromSource(
+ contents: string,
+ { compileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string }
+): Promise<TransformResult> {
+ const fileID = path.relative(projectRoot, filename);
+ switch (path.extname(filename) as SupportedExtensions) {
+ case '.astro':
+ return convertAstroToJsx(contents, { compileOptions, filename, fileID });
+ case '.md':
+ return convertMdToJsx(contents, { compileOptions, filename, fileID });
+ default:
+ throw new Error('Not Supported!');
+ }
+}
+
+
+export async function compileComponent(
+ source: string,
+ { compileOptions = defaultCompileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string }
+): Promise<CompileResult> {
+ const sourceJsx = await transformFromSource(source, { compileOptions, filename, projectRoot });
+ const isPage = path.extname(filename) === '.md' || sourceJsx.items.some((item) => item.name === 'html');
+ // sort <style> tags first
+ sourceJsx.items.sort((a, b) => (a.name === 'style' && b.name !== 'style' ? -1 : 0));
+
+ // return template
+ let modJsx = `
+import fetch from 'node-fetch';
+
+// <script astro></script>
+${sourceJsx.imports.join('\n')}
+
+// \`__render()\`: Render the contents of the Astro module.
+import { h, Fragment } from '${internalImport('h.js')}';
+async function __render(props, ...children) {
+ ${sourceJsx.script}
+ return h(Fragment, null, ${sourceJsx.items.map(({ jsx }) => jsx).join(',')});
+}
+export default __render;
+`;
+
+ if (isPage) {
+ modJsx += `
+// \`__renderPage()\`: Render the contents of the Astro module as a page. This is a special flow,
+// triggered by loading a component directly by URL.
+export async function __renderPage({request, children, props}) {
+
+ const currentChild = {
+ setup: typeof setup === 'undefined' ? (passthrough) => passthrough : setup,
+ layout: typeof __layout === 'undefined' ? undefined : __layout,
+ content: typeof __content === 'undefined' ? undefined : __content,
+ __render,
+ };
+
+ await currentChild.setup({request});
+ const childBodyResult = await currentChild.__render(props, children);
+
+ // find layout, if one was given.
+ if (currentChild.layout) {
+ const layoutComponent = (await import('/_astro/layouts/' + currentChild.layout.replace(/.*layouts\\//, "").replace(/\.astro$/, '.js')));
+ return layoutComponent.__renderPage({
+ request,
+ props: {content: currentChild.content},
+ children: [childBodyResult],
+ });
+ }
+
+ return childBodyResult;
+};\n`;
+ } else {
+ modJsx += `
+export async function __renderPage() { throw new Error("No <html> page element found!"); }\n`;
+ }
+
+ return {
+ result: sourceJsx,
+ contents: modJsx,
+ };
+}
diff --git a/src/optimize/index.ts b/src/compiler/optimize/index.ts
index 9f8ec2f05..4f6e54fa5 100644
--- a/src/optimize/index.ts
+++ b/src/compiler/optimize/index.ts
@@ -1,6 +1,6 @@
import { walk } from 'estree-walker';
-import type { Ast, TemplateNode } from '../compiler/interfaces';
-import { NodeVisitor, Optimizer, VisitorFn } from '../@types/optimizer';
+import type { Ast, TemplateNode } from '../../parser/interfaces';
+import { NodeVisitor, Optimizer, VisitorFn } from '../../@types/optimizer';
import optimizeStyles from './styles.js';
interface VisitorCollection {
diff --git a/src/optimize/styles.ts b/src/compiler/optimize/styles.ts
index c69bee504..691300067 100644
--- a/src/optimize/styles.ts
+++ b/src/compiler/optimize/styles.ts
@@ -5,8 +5,8 @@ import postcss from 'postcss';
import postcssModules from 'postcss-modules';
import findUp from 'find-up';
import sass from 'sass';
-import { Optimizer } from '../@types/optimizer';
-import type { TemplateNode } from '../compiler/interfaces';
+import { Optimizer } from '../../@types/optimizer';
+import type { TemplateNode } from '../../parser/interfaces';
type StyleType = 'css' | 'scss' | 'sass' | 'postcss';
diff --git a/src/logger.ts b/src/logger.ts
index 4bdac162a..6634c5092 100644
--- a/src/logger.ts
+++ b/src/logger.ts
@@ -1,4 +1,4 @@
-import type { CompileError } from './compiler/utils/error.js';
+import type { CompileError } from './parser/utils/error.js';
import { bold, blue, red, grey, underline } from 'kleur/colors';
import { Writable } from 'stream';
import { format as utilFormat } from 'util';
diff --git a/src/micromark-collect-headers.ts b/src/micromark-collect-headers.ts
index d69a0a358..78567699c 100644
--- a/src/micromark-collect-headers.ts
+++ b/src/micromark-collect-headers.ts
@@ -28,7 +28,6 @@ export function createMarkdownHeadersCollector() {
this.tag(`<h${currentHeader.depth} id="${currentHeader.slug}">`);
this.raw(currentHeader.text);
this.tag(`</h${currentHeader.depth}>`);
- // console.log(this.sliceSerialize(node));
},
} as any,
} as any,
diff --git a/src/compiler/README.md b/src/parser/README.md
index f44d45ecf..f44d45ecf 100644
--- a/src/compiler/README.md
+++ b/src/parser/README.md
diff --git a/src/compiler/Stats.ts b/src/parser/Stats.ts
index 33802a42b..33802a42b 100644
--- a/src/compiler/Stats.ts
+++ b/src/parser/Stats.ts
diff --git a/src/compiler/config.ts b/src/parser/config.ts
index e6d0f65a7..e6d0f65a7 100644
--- a/src/compiler/config.ts
+++ b/src/parser/config.ts
diff --git a/src/parser/index.ts b/src/parser/index.ts
new file mode 100644
index 000000000..718199c94
--- /dev/null
+++ b/src/parser/index.ts
@@ -0,0 +1 @@
+export { default as parse } from './parse/index.js';
diff --git a/src/compiler/interfaces.ts b/src/parser/interfaces.ts
index b77357d23..89c99aa20 100644
--- a/src/compiler/interfaces.ts
+++ b/src/parser/interfaces.ts
@@ -1,5 +1,5 @@
-import { Node, Program } from 'estree';
-import { SourceMap } from 'magic-string';
+import type { Expression, Program } from '@babel/types';
+import type { SourceMap } from 'magic-string';
interface BaseNode {
start: number;
@@ -21,7 +21,7 @@ export interface Text extends BaseNode {
export interface MustacheTag extends BaseNode {
type: 'MustacheTag';
- expression: string;
+ content: string;
}
export type DirectiveType = 'Action' | 'Animation' | 'Binding' | 'Class' | 'EventHandler' | 'Let' | 'Ref' | 'Transition';
diff --git a/src/compiler/parse/acorn.ts b/src/parser/parse/acorn.ts
index c70756d79..7fc0f8f67 100644
--- a/src/compiler/parse/acorn.ts
+++ b/src/parser/parse/acorn.ts
@@ -39,4 +39,4 @@ export const parse_expression_at = (source: string, index: number): number => {
// sourceType: 'module',
// ecmaVersion: 2020,
// locations: true,
-// });
+// }); \ No newline at end of file
diff --git a/src/compiler/parse/index.ts b/src/parser/parse/index.ts
index 052cf0317..052cf0317 100644
--- a/src/compiler/parse/index.ts
+++ b/src/parser/parse/index.ts
diff --git a/src/compiler/parse/read/context.ts b/src/parser/parse/read/context.ts
index 4d8f12060..4d8f12060 100644
--- a/src/compiler/parse/read/context.ts
+++ b/src/parser/parse/read/context.ts
diff --git a/src/compiler/parse/read/expression.ts b/src/parser/parse/read/expression.ts
index 1fe5f05f1..f691f4772 100644
--- a/src/compiler/parse/read/expression.ts
+++ b/src/parser/parse/read/expression.ts
@@ -39,4 +39,4 @@ export default function read_expression(parser: Parser): string {
} catch (err) {
parser.acorn_error(err);
}
-}
+} \ No newline at end of file
diff --git a/src/compiler/parse/read/script.ts b/src/parser/parse/read/script.ts
index 7afbfb08f..7afbfb08f 100644
--- a/src/compiler/parse/read/script.ts
+++ b/src/parser/parse/read/script.ts
diff --git a/src/compiler/parse/read/style.ts b/src/parser/parse/read/style.ts
index f23d7b10e..f23d7b10e 100644
--- a/src/compiler/parse/read/style.ts
+++ b/src/parser/parse/read/style.ts
diff --git a/src/compiler/parse/state/fragment.ts b/src/parser/parse/state/fragment.ts
index 97398b227..97398b227 100644
--- a/src/compiler/parse/state/fragment.ts
+++ b/src/parser/parse/state/fragment.ts
diff --git a/src/compiler/parse/state/mustache.ts b/src/parser/parse/state/mustache.ts
index 79372d8d9..8ffac4f85 100644
--- a/src/compiler/parse/state/mustache.ts
+++ b/src/parser/parse/state/mustache.ts
@@ -397,7 +397,7 @@ export default function mustache(parser: Parser) {
// });
throw new Error('@debug not yet supported');
} else {
- const expression = read_expression(parser);
+ const content = read_expression(parser);
parser.allow_whitespace();
parser.eat('}', true);
@@ -407,7 +407,7 @@ export default function mustache(parser: Parser) {
start,
end: parser.index,
type: 'MustacheTag',
- expression,
+ content,
});
}
}
diff --git a/src/compiler/parse/state/setup.ts b/src/parser/parse/state/setup.ts
index f64d8c52b..f64d8c52b 100644
--- a/src/compiler/parse/state/setup.ts
+++ b/src/parser/parse/state/setup.ts
diff --git a/src/compiler/parse/state/tag.ts b/src/parser/parse/state/tag.ts
index c6684874c..1003be14c 100644
--- a/src/compiler/parse/state/tag.ts
+++ b/src/parser/parse/state/tag.ts
@@ -351,7 +351,7 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
parser.allow_whitespace();
if (parser.eat('...')) {
- const expression = read_expression(parser);
+ const {expression} = read_expression(parser);
parser.allow_whitespace();
parser.eat('}', true);
@@ -549,7 +549,7 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] {
flush();
parser.allow_whitespace();
- const expression = read_expression(parser);
+ const content = read_expression(parser);
parser.allow_whitespace();
parser.eat('}', true);
@@ -557,7 +557,7 @@ function read_sequence(parser: Parser, done: () => boolean): TemplateNode[] {
start: index,
end: parser.index,
type: 'MustacheTag',
- expression,
+ content,
});
current_chunk = {
diff --git a/src/compiler/parse/state/text.ts b/src/parser/parse/state/text.ts
index cca83f2d4..cca83f2d4 100644
--- a/src/compiler/parse/state/text.ts
+++ b/src/parser/parse/state/text.ts
diff --git a/src/compiler/parse/utils/bracket.ts b/src/parser/parse/utils/bracket.ts
index 7e885ad78..7e885ad78 100644
--- a/src/compiler/parse/utils/bracket.ts
+++ b/src/parser/parse/utils/bracket.ts
diff --git a/src/compiler/parse/utils/entities.ts b/src/parser/parse/utils/entities.ts
index e554664eb..e554664eb 100644
--- a/src/compiler/parse/utils/entities.ts
+++ b/src/parser/parse/utils/entities.ts
diff --git a/src/compiler/parse/utils/html.ts b/src/parser/parse/utils/html.ts
index 3b406c9cc..3b406c9cc 100644
--- a/src/compiler/parse/utils/html.ts
+++ b/src/parser/parse/utils/html.ts
diff --git a/src/compiler/parse/utils/node.ts b/src/parser/parse/utils/node.ts
index 45769f96e..45769f96e 100644
--- a/src/compiler/parse/utils/node.ts
+++ b/src/parser/parse/utils/node.ts
diff --git a/src/compiler/utils/error.ts b/src/parser/utils/error.ts
index 3c1b23e4c..3c1b23e4c 100644
--- a/src/compiler/utils/error.ts
+++ b/src/parser/utils/error.ts
diff --git a/src/compiler/utils/full_char_code_at.ts b/src/parser/utils/full_char_code_at.ts
index fea5151b6..fea5151b6 100644
--- a/src/compiler/utils/full_char_code_at.ts
+++ b/src/parser/utils/full_char_code_at.ts
diff --git a/src/compiler/utils/fuzzymatch.ts b/src/parser/utils/fuzzymatch.ts
index d24d0fd0a..d24d0fd0a 100644
--- a/src/compiler/utils/fuzzymatch.ts
+++ b/src/parser/utils/fuzzymatch.ts
diff --git a/src/compiler/utils/get_code_frame.ts b/src/parser/utils/get_code_frame.ts
index a0c296672..a0c296672 100644
--- a/src/compiler/utils/get_code_frame.ts
+++ b/src/parser/utils/get_code_frame.ts
diff --git a/src/compiler/utils/link.ts b/src/parser/utils/link.ts
index 0dc5af1b7..0dc5af1b7 100644
--- a/src/compiler/utils/link.ts
+++ b/src/parser/utils/link.ts
diff --git a/src/compiler/utils/list.ts b/src/parser/utils/list.ts
index ba1ef9f4c..ba1ef9f4c 100644
--- a/src/compiler/utils/list.ts
+++ b/src/parser/utils/list.ts
diff --git a/src/compiler/utils/names.ts b/src/parser/utils/names.ts
index f2e1dfc8e..f2e1dfc8e 100644
--- a/src/compiler/utils/names.ts
+++ b/src/parser/utils/names.ts
diff --git a/src/compiler/utils/namespaces.ts b/src/parser/utils/namespaces.ts
index 5f61beff9..5f61beff9 100644
--- a/src/compiler/utils/namespaces.ts
+++ b/src/parser/utils/namespaces.ts
diff --git a/src/compiler/utils/nodes_match.ts b/src/parser/utils/nodes_match.ts
index 563742635..563742635 100644
--- a/src/compiler/utils/nodes_match.ts
+++ b/src/parser/utils/nodes_match.ts
diff --git a/src/compiler/utils/patterns.ts b/src/parser/utils/patterns.ts
index 317a7c199..317a7c199 100644
--- a/src/compiler/utils/patterns.ts
+++ b/src/parser/utils/patterns.ts
diff --git a/src/compiler/utils/trim.ts b/src/parser/utils/trim.ts
index 406a8c97f..406a8c97f 100644
--- a/src/compiler/utils/trim.ts
+++ b/src/parser/utils/trim.ts
diff --git a/src/runtime.ts b/src/runtime.ts
index aff5ee7d2..4b5d51f07 100644
--- a/src/runtime.ts
+++ b/src/runtime.ts
@@ -1,7 +1,7 @@
import type { SnowpackDevServer, ServerRuntime as SnowpackServerRuntime, LoadResult as SnowpackLoadResult } from 'snowpack';
import type { AstroConfig } from './@types/astro';
import type { LogOptions } from './logger';
-import type { CompileError } from './compiler/utils/error.js';
+import type { CompileError } from './parser/utils/error.js';
import { info, error, parseError } from './logger.js';
import { existsSync, promises as fsPromises } from 'fs';
diff --git a/src/transform2.ts b/src/transform2.ts
deleted file mode 100644
index 47c3659e7..000000000
--- a/src/transform2.ts
+++ /dev/null
@@ -1,172 +0,0 @@
-import type { LogOptions } from './logger.js';
-
-import path from 'path';
-import micromark from 'micromark';
-import gfmSyntax from 'micromark-extension-gfm';
-import matter from 'gray-matter';
-import gfmHtml from 'micromark-extension-gfm/html.js';
-import { CompileResult, TransformResult } from './@types/astro';
-import { parse } from './compiler/index.js';
-import { createMarkdownHeadersCollector } from './micromark-collect-headers.js';
-import { encodeMarkdown } from './micromark-encode.js';
-import { defaultLogOptions } from './logger.js';
-import { optimize } from './optimize/index.js';
-import { codegen } from './codegen/index.js';
-
-interface CompileOptions {
- logging: LogOptions;
- resolve: (p: string) => string;
-}
-
-const defaultCompileOptions: CompileOptions = {
- logging: defaultLogOptions,
- resolve: (p: string) => p,
-};
-
-function internalImport(internalPath: string) {
- return `/_astro_internal/${internalPath}`;
-}
-
-interface ConvertAstroOptions {
- compileOptions: CompileOptions;
- filename: string;
- fileID: string;
-}
-
-async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): Promise<TransformResult> {
- const { filename } = opts;
-
- // 1. Parse
- const ast = parse(template, {
- filename,
- });
-
- // 2. Optimize the AST
- await optimize(ast, opts);
-
- // Turn AST into JSX
- return await codegen(ast, opts);
-}
-
-async function convertMdToJsx(
- contents: string,
- { compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string }
-): Promise<TransformResult> {
- const { data: frontmatterData, content } = matter(contents);
- const { headers, headersExtension } = createMarkdownHeadersCollector();
- const mdHtml = micromark(content, {
- allowDangerousHtml: true,
- extensions: [gfmSyntax()],
- htmlExtensions: [gfmHtml, encodeMarkdown, headersExtension],
- });
-
- // TODO: Warn if reserved word is used in "frontmatterData"
- const contentData: any = {
- ...frontmatterData,
- headers,
- source: content,
- html: mdHtml,
- };
-
- let imports = '';
- for (let [ComponentName, specifier] of Object.entries(frontmatterData.import || {})) {
- imports += `import ${ComponentName} from '${specifier}';\n`;
- }
-
- // </script> can't be anywhere inside of a JS string, otherwise the HTML parser fails.
- // Break it up here so that the HTML parser won't detect it.
- const stringifiedSetupContext = JSON.stringify(contentData).replace(/\<\/script\>/g, `</scrip" + "t>`);
-
- const raw = `---
- ${imports}
- ${frontmatterData.layout ? `const __layout = ${JSON.stringify(frontmatterData.layout)};` : ''}
- const __content = ${stringifiedSetupContext};
----
-<section>${mdHtml}</section>`;
-
- const convertOptions = { compileOptions, filename, fileID };
-
- return convertAstroToJsx(raw, convertOptions);
-}
-
-type SupportedExtensions = '.astro' | '.md';
-
-async function transformFromSource(
- contents: string,
- { compileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string }
-): Promise<TransformResult> {
- const fileID = path.relative(projectRoot, filename);
- switch (path.extname(filename) as SupportedExtensions) {
- case '.astro':
- return convertAstroToJsx(contents, { compileOptions, filename, fileID });
- case '.md':
- return convertMdToJsx(contents, { compileOptions, filename, fileID });
- default:
- throw new Error('Not Supported!');
- }
-}
-
-export async function compileComponent(
- source: string,
- { compileOptions = defaultCompileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string }
-): Promise<CompileResult> {
- const sourceJsx = await transformFromSource(source, { compileOptions, filename, projectRoot });
-
- // sort <style> tags first
- // TODO: remove these and inject in <head>
- const isPage = path.extname(filename) === '.md' || sourceJsx.items.some((item) => item.name === 'html');
- sourceJsx.items.sort((a, b) => (a.name === 'style' && b.name !== 'style' ? -1 : 0));
-
- // return template
- let modJsx = `
-// <script astro></script>
-${sourceJsx.script}
-
-// \`__render()\`: Render the contents of the Astro module.
-import { h, Fragment } from '${internalImport('h.js')}';
-function __render(props, ...children) {
- ${sourceJsx.props.map((p) => `${p} = props.${p} ?? ${p};`).join('\n')}
- return h(Fragment, null, ${sourceJsx.items.map(({ jsx }) => jsx).join(',')});
-}
-export default __render;
-`;
-
- if (isPage) {
- modJsx += `
-// \`__renderPage()\`: Render the contents of the Astro module as a page. This is a special flow,
-// triggered by loading a component directly by URL.
-export async function __renderPage({request, children, props}) {
-
- const currentChild = {
- setup: typeof setup === 'undefined' ? (passthrough) => passthrough : setup,
- layout: typeof __layout === 'undefined' ? undefined : __layout,
- content: typeof __content === 'undefined' ? undefined : __content,
- __render,
- };
-
- const fetch = (await import('node-fetch')).default;
- await currentChild.setup({request, fetch});
- const childBodyResult = await currentChild.__render(props, children);
-
- // find layout, if one was given.
- if (currentChild.layout) {
- const layoutComponent = (await import('/_astro/layouts/' + currentChild.layout.replace(/.*layouts\\//, "").replace(/\.astro$/, '.js')));
- return layoutComponent.__renderPage({
- request,
- props: {content: currentChild.content},
- children: [childBodyResult],
- });
- }
-
- return childBodyResult;
-};\n`;
- } else {
- modJsx += `
-export async function __renderPage() { throw new Error("No <html> page element found!"); }\n`;
- }
-
- return {
- result: sourceJsx,
- contents: modJsx,
- };
-}