diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/codegen.ts | 67 | ||||
-rw-r--r-- | src/compiler/index.ts | 8 | ||||
-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}'`; } } } |