summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/codegen.ts67
-rw-r--r--src/compiler/index.ts8
-rw-r--r--src/compiler/transform/doctype.ts (renamed from src/compiler/optimize/doctype.ts)6
-rw-r--r--src/compiler/transform/index.ts (renamed from src/compiler/optimize/index.ts)36
-rw-r--r--src/compiler/transform/module-scripts.ts (renamed from src/compiler/optimize/module-scripts.ts)6
-rw-r--r--src/compiler/transform/postcss-scoped-styles/index.ts (renamed from src/compiler/optimize/postcss-scoped-styles/index.ts)0
-rw-r--r--src/compiler/transform/prism.ts (renamed from src/compiler/optimize/prism.ts)11
-rw-r--r--src/compiler/transform/styles.ts (renamed from src/compiler/optimize/styles.ts)10
8 files changed, 72 insertions, 72 deletions
diff --git a/src/compiler/codegen.ts b/src/compiler/codegen.ts
index 59cc2c702..8bcf3f49d 100644
--- a/src/compiler/codegen.ts
+++ b/src/compiler/codegen.ts
@@ -78,9 +78,10 @@ function getAttributes(attrs: Attribute[]): Record<string, string> {
continue;
}
switch (val.type) {
- case 'MustacheTag':
- result[attr.name] = '(' + val.content + ')';
+ case 'MustacheTag': {
+ result[attr.name] = '(' + val.expression.codeStart + ')';
continue;
+ }
case 'Text':
result[attr.name] = JSON.stringify(getTextFromAttribute(val));
continue;
@@ -93,13 +94,21 @@ function getAttributes(attrs: Attribute[]): Record<string, string> {
/** Get value from a TemplateNode Attribute (text attributes only!) */
function getTextFromAttribute(attr: any): string {
- if (attr.raw !== undefined) {
- return attr.raw;
- }
- if (attr.data !== undefined) {
- return attr.data;
+ switch(attr.type) {
+ case 'Text': {
+ if (attr.raw !== undefined) {
+ return attr.raw;
+ }
+ if (attr.data !== undefined) {
+ return attr.data;
+ }
+ break;
+ }
+ case 'MustacheTag': {
+ return attr.expression.codeStart;
+ }
}
- throw new Error('UNKNOWN attr');
+ throw new Error(`Unknown attribute type ${attr.type}`);
}
/** Convert TemplateNode attributes to string */
@@ -238,7 +247,7 @@ function getComponentWrapper(_name: string, { type, plugin, url }: ComponentInfo
}
}
-/** Evaluate mustache expression (safely) */
+/** Evaluate expression (safely) */
function compileExpressionSafe(raw: string): string {
let { code } = transformSync(raw, {
loader: 'tsx',
@@ -468,33 +477,19 @@ function compileHtml(enterNode: TemplateNode, state: CodegenState, compileOption
walk(enterNode, {
enter(node: TemplateNode) {
switch (node.type) {
- case 'MustacheTag':
- let code = compileExpressionSafe(node.content);
-
- let matches: RegExpExecArray[] = [];
- let match: RegExpExecArray | null | undefined;
- const H_COMPONENT_SCANNER = /h\(['"]?([A-Z].*?)['"]?,/gs;
- const regex = new RegExp(H_COMPONENT_SCANNER);
- while ((match = regex.exec(code))) {
- matches.push(match);
- }
- for (const astroComponent of matches.reverse()) {
- const name = astroComponent[1];
- const [componentName, componentKind] = name.split(':');
- if (!components[componentName]) {
- throw new Error(`Unknown Component: ${componentName}`);
- }
- const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], { astroConfig, dynamicImports, filename });
- if (wrapperImport) {
- importExportStatements.add(wrapperImport);
- }
- if (wrapper !== name) {
- code = code.slice(0, astroComponent.index + 2) + wrapper + code.slice(astroComponent.index + astroComponent[0].length - 1);
- }
+ case 'Expression': {
+ let child = '';
+ if(node.children!.length) {
+ child = compileHtml(node.children![0], state, compileOptions);
}
- outSource += `,(${code.trim().replace(/\;$/, '')})`;
+ let raw = node.codeStart + child + node.codeEnd;
+ // TODO Do we need to compile this now, or should we compile the entire module at the end?
+ let code = compileExpressionSafe(raw).trim().replace(/\;$/, '');
+ outSource += `,(${code})`;
this.skip();
- return;
+ break;
+ }
+ case 'MustacheTag':
case 'Comment':
return;
case 'Fragment':
@@ -557,11 +552,11 @@ function compileHtml(enterNode: TemplateNode, state: CodegenState, compileOption
leave(node, parent, prop, index) {
switch (node.type) {
case 'Text':
- case 'MustacheTag':
case 'Attribute':
case 'Comment':
- return;
case 'Fragment':
+ case 'Expression':
+ case 'MustacheTag':
return;
case 'Slot':
case 'Head':
diff --git a/src/compiler/index.ts b/src/compiler/index.ts
index d33527b9b..db50abec8 100644
--- a/src/compiler/index.ts
+++ b/src/compiler/index.ts
@@ -11,7 +11,7 @@ import { parse } from '../parser/index.js';
import { createMarkdownHeadersCollector } from './markdown/micromark-collect-headers.js';
import { encodeMarkdown } from './markdown/micromark-encode.js';
import { encodeAstroMdx } from './markdown/micromark-mdx-astro.js';
-import { optimize } from './optimize/index.js';
+import { transform } from './transform/index.js';
import { codegen } from './codegen.js';
/** Return Astro internal import URL */
@@ -29,7 +29,7 @@ interface ConvertAstroOptions {
* .astro -> .jsx
* Core function processing .astro files. Initiates all 3 phases of compilation:
* 1. Parse
- * 2. Optimize
+ * 2. Transform
* 3. Codegen
*/
async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): Promise<TransformResult> {
@@ -40,8 +40,8 @@ async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): P
filename,
});
- // 2. Optimize the AST
- await optimize(ast, opts);
+ // 2. Transform the AST
+ await transform(ast, opts);
// 3. Turn AST into JSX
return await codegen(ast, opts);
diff --git a/src/compiler/optimize/doctype.ts b/src/compiler/transform/doctype.ts
index 176880c08..d19b01f81 100644
--- a/src/compiler/optimize/doctype.ts
+++ b/src/compiler/transform/doctype.ts
@@ -1,7 +1,7 @@
-import { Optimizer } from '../../@types/optimizer';
+import { Transformer } from '../../@types/transformer';
-/** Optimize <!doctype> tg */
-export default function (_opts: { filename: string; fileID: string }): Optimizer {
+/** Transform <!doctype> tg */
+export default function (_opts: { filename: string; fileID: string }): Transformer {
let hasDoctype = false;
return {
diff --git a/src/compiler/optimize/index.ts b/src/compiler/transform/index.ts
index fcbd6e950..6a81b92b0 100644
--- a/src/compiler/optimize/index.ts
+++ b/src/compiler/transform/index.ts
@@ -1,13 +1,13 @@
import type { Ast, TemplateNode } from '../../parser/interfaces';
-import type { NodeVisitor, OptimizeOptions, Optimizer, VisitorFn } from '../../@types/optimizer';
+import type { NodeVisitor, TransformOptions, Transformer, VisitorFn } from '../../@types/transformer';
import { walk } from 'estree-walker';
-// Optimizers
-import optimizeStyles from './styles.js';
-import optimizeDoctype from './doctype.js';
-import optimizeModuleScripts from './module-scripts.js';
-import optimizeCodeBlocks from './prism.js';
+// Transformers
+import transformStyles from './styles.js';
+import transformDoctype from './doctype.js';
+import transformModuleScripts from './module-scripts.js';
+import transformCodeBlocks from './prism.js';
interface VisitorCollection {
enter: Map<string, VisitorFn[]>;
@@ -24,23 +24,23 @@ function addVisitor(visitor: NodeVisitor, collection: VisitorCollection, nodeNam
collection[event].set(nodeName, visitors);
}
-/** Compile visitor actions from optimizer */
-function collectVisitors(optimizer: Optimizer, htmlVisitors: VisitorCollection, cssVisitors: VisitorCollection, finalizers: Array<() => Promise<void>>) {
- if (optimizer.visitors) {
- if (optimizer.visitors.html) {
- for (const [nodeName, visitor] of Object.entries(optimizer.visitors.html)) {
+/** Compile visitor actions from transformer */
+function collectVisitors(transformer: Transformer, htmlVisitors: VisitorCollection, cssVisitors: VisitorCollection, finalizers: Array<() => Promise<void>>) {
+ if (transformer.visitors) {
+ if (transformer.visitors.html) {
+ for (const [nodeName, visitor] of Object.entries(transformer.visitors.html)) {
addVisitor(visitor, htmlVisitors, nodeName, 'enter');
addVisitor(visitor, htmlVisitors, nodeName, 'leave');
}
}
- if (optimizer.visitors.css) {
- for (const [nodeName, visitor] of Object.entries(optimizer.visitors.css)) {
+ if (transformer.visitors.css) {
+ for (const [nodeName, visitor] of Object.entries(transformer.visitors.css)) {
addVisitor(visitor, cssVisitors, nodeName, 'enter');
addVisitor(visitor, cssVisitors, nodeName, 'leave');
}
}
}
- finalizers.push(optimizer.finalize);
+ finalizers.push(transformer.finalize);
}
/** Utility for formatting visitors */
@@ -74,17 +74,17 @@ function walkAstWithVisitors(tmpl: TemplateNode, collection: VisitorCollection)
}
/**
- * Optimize
+ * Transform
* Step 2/3 in Astro SSR.
- * Optimize is the point at which we mutate the AST before sending off to
+ * Transform is the point at which we mutate the AST before sending off to
* Codegen, and then to Snowpack. In some ways, it‘s a preprocessor.
*/
-export async function optimize(ast: Ast, opts: OptimizeOptions) {
+export async function transform(ast: Ast, opts: TransformOptions) {
const htmlVisitors = createVisitorCollection();
const cssVisitors = createVisitorCollection();
const finalizers: Array<() => Promise<void>> = [];
- const optimizers = [optimizeStyles(opts), optimizeDoctype(opts), optimizeModuleScripts(opts), optimizeCodeBlocks(ast.module)];
+ const optimizers = [transformStyles(opts), transformDoctype(opts), transformModuleScripts(opts), transformCodeBlocks(ast.module)];
for (const optimizer of optimizers) {
collectVisitors(optimizer, htmlVisitors, cssVisitors, finalizers);
diff --git a/src/compiler/optimize/module-scripts.ts b/src/compiler/transform/module-scripts.ts
index 9d4949215..aff1ec4f6 100644
--- a/src/compiler/optimize/module-scripts.ts
+++ b/src/compiler/transform/module-scripts.ts
@@ -1,11 +1,11 @@
-import type { Optimizer } from '../../@types/optimizer';
+import type { Transformer } from '../../@types/transformer';
import type { CompileOptions } from '../../@types/compiler';
import path from 'path';
import { getAttrValue, setAttrValue } from '../../ast.js';
-/** Optimize <script type="module"> */
-export default function ({ compileOptions, filename }: { compileOptions: CompileOptions; filename: string; fileID: string }): Optimizer {
+/** Transform <script type="module"> */
+export default function ({ compileOptions, filename }: { compileOptions: CompileOptions; filename: string; fileID: string }): Transformer {
const { astroConfig } = compileOptions;
const { astroRoot } = astroConfig;
const fileUrl = new URL(`file://${filename}`);
diff --git a/src/compiler/optimize/postcss-scoped-styles/index.ts b/src/compiler/transform/postcss-scoped-styles/index.ts
index 23350869c..23350869c 100644
--- a/src/compiler/optimize/postcss-scoped-styles/index.ts
+++ b/src/compiler/transform/postcss-scoped-styles/index.ts
diff --git a/src/compiler/optimize/prism.ts b/src/compiler/transform/prism.ts
index 5c5364796..628dcce7e 100644
--- a/src/compiler/optimize/prism.ts
+++ b/src/compiler/transform/prism.ts
@@ -1,4 +1,4 @@
-import type { Optimizer } from '../../@types/optimizer';
+import type { Transformer } from '../../@types/transformer';
import type { Script } from '../../parser/interfaces';
import { getAttrValue } from '../../ast.js';
@@ -11,7 +11,7 @@ function escape(code: string) {
});
}
-export default function (module: Script): Optimizer {
+export default function (module: Script): Transformer {
let usesPrism = false;
return {
@@ -61,7 +61,12 @@ export default function (module: Script): Optimizer {
value: [
{
type: 'MustacheTag',
- content: '`' + escape(code) + '`',
+ expression: {
+ type: 'Expression',
+ codeStart: '`' + escape(code) + '`',
+ codeEnd: '',
+ children: []
+ }
},
],
},
diff --git a/src/compiler/optimize/styles.ts b/src/compiler/transform/styles.ts
index 807d869c9..d8e3196a1 100644
--- a/src/compiler/optimize/styles.ts
+++ b/src/compiler/transform/styles.ts
@@ -7,7 +7,7 @@ import postcssKeyframes from 'postcss-icss-keyframes';
import findUp from 'find-up';
import sass from 'sass';
import type { RuntimeMode } from '../../@types/astro';
-import type { OptimizeOptions, Optimizer } from '../../@types/optimizer';
+import type { TransformOptions, Transformer } from '../../@types/transformer';
import type { TemplateNode } from '../../parser/interfaces';
import { debug } from '../../logger.js';
import astroScopedStyles, { NEVER_SCOPED_TAGS } from './postcss-scoped-styles/index.js';
@@ -152,8 +152,8 @@ async function transformStyle(code: string, { type, filename, scopedClass, mode
return { css, type: styleType };
}
-/** Optimize <style> tags */
-export default function optimizeStyles({ compileOptions, filename, fileID }: OptimizeOptions): Optimizer {
+/** Transform <style> tags */
+export default function transformStyles({ compileOptions, filename, fileID }: TransformOptions): Transformer {
const styleNodes: TemplateNode[] = []; // <style> tags to be updated
const styleTransformPromises: Promise<StyleTransformResult>[] = []; // async style transform results to be finished in finalize();
const scopedClass = `astro-${hashFromFilename(fileID)}`; // this *should* generate same hash from fileID every time
@@ -218,9 +218,9 @@ export default function optimizeStyles({ compileOptions, filename, fileID }: Opt
}
} else if (attr.value[k].type === 'MustacheTag' && attr.value[k]) {
// don‘t add same scopedClass twice (this check is a little more basic, but should suffice)
- if (!attr.value[k].content.includes(`' ${scopedClass}'`)) {
+ if (!attr.value[k].expression.codeStart.includes(`' ${scopedClass}'`)) {
// MustacheTag
- attr.value[k].content = `(${attr.value[k].content}) + ' ${scopedClass}'`;
+ attr.value[k].expression.codeStart = `(${attr.value[k].expression.codeStart}) + ' ${scopedClass}'`;
}
}
}