diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/codegen.ts | 24 | ||||
-rw-r--r-- | src/compiler/index.ts | 16 | ||||
-rw-r--r-- | src/compiler/optimize/doctype.ts | 1 | ||||
-rw-r--r-- | src/compiler/optimize/index.ts | 10 | ||||
-rw-r--r-- | src/compiler/optimize/module-scripts.ts | 1 | ||||
-rw-r--r-- | src/compiler/optimize/postcss-scoped-styles/index.ts | 20 | ||||
-rw-r--r-- | src/compiler/optimize/styles.ts | 2 |
7 files changed, 59 insertions, 15 deletions
diff --git a/src/compiler/codegen.ts b/src/compiler/codegen.ts index 63fc44dfb..2486ef92f 100644 --- a/src/compiler/codegen.ts +++ b/src/compiler/codegen.ts @@ -30,10 +30,12 @@ interface CodeGenOptions { fileID: string; } +/** Format Astro internal import URL */ function internalImport(internalPath: string) { return `/_astro_internal/${internalPath}`; } +/** Retrieve attributes from TemplateNode */ function getAttributes(attrs: Attribute[]): Record<string, string> { let result: Record<string, string> = {}; for (const attr of attrs) { @@ -79,6 +81,7 @@ function getAttributes(attrs: Attribute[]): Record<string, string> { return result; } +/** Get value from a TemplateNode Attribute (text attributes only!) */ function getTextFromAttribute(attr: any): string { if (attr.raw !== undefined) { return attr.raw; @@ -89,6 +92,7 @@ function getTextFromAttribute(attr: any): string { throw new Error('UNKNOWN attr'); } +/** Convert TemplateNode attributes to string */ function generateAttributes(attrs: Record<string, string>): string { let result = '{'; for (const [key, val] of Object.entries(attrs)) { @@ -117,6 +121,8 @@ interface GetComponentWrapperOptions { astroConfig: AstroConfig; dynamicImports: DynamicImportMap; } + +/** Generate Astro-friendly component import */ function getComponentWrapper(_name: string, { type, plugin, url }: ComponentInfo, opts: GetComponentWrapperOptions) { const { astroConfig, dynamicImports, filename } = opts; const { astroRoot } = astroConfig; @@ -222,6 +228,7 @@ function getComponentWrapper(_name: string, { type, plugin, url }: ComponentInfo } } +/** Evaluate mustache expression (safely) */ function compileExpressionSafe(raw: string): string { let { code } = transformSync(raw, { loader: 'tsx', @@ -232,6 +239,7 @@ function compileExpressionSafe(raw: string): string { return code; } +/** Build dependency map of dynamic component runtime frameworks */ async function acquireDynamicComponentImports(plugins: Set<ValidExtensionPlugins>, resolve: (s: string) => Promise<string>): Promise<DynamicImportMap> { const importMap: DynamicImportMap = new Map(); for (let plugin of plugins) { @@ -254,7 +262,15 @@ async function acquireDynamicComponentImports(plugins: Set<ValidExtensionPlugins return importMap; } -export async function codegen(ast: Ast, { compileOptions, filename, fileID }: CodeGenOptions): Promise<TransformResult> { +/** + * Codegen + * Step 3/3 in Astro SSR. + * This is the final pass over a document AST before it‘s converted to an h() function + * and handed off to Snowpack to build. + * @param {Ast} AST The parsed AST to crawl + * @param {object} CodeGenOptions + */ +export async function codegen(ast: Ast, { compileOptions, filename }: CodeGenOptions): Promise<TransformResult> { const { extensions = defaultExtensions, astroConfig } = compileOptions; await eslexer.init; @@ -364,8 +380,8 @@ export async function codegen(ast: Ast, { compileOptions, filename, fileID }: Co while ((match = regex.exec(code))) { matches.push(match); } - for (const match of matches.reverse()) { - const name = match[1]; + for (const astroComponent of matches.reverse()) { + const name = astroComponent[1]; const [componentName, componentKind] = name.split(':'); if (!components[componentName]) { throw new Error(`Unknown Component: ${componentName}`); @@ -375,7 +391,7 @@ export async function codegen(ast: Ast, { compileOptions, filename, fileID }: Co importExportStatements.add(wrapperImport); } if (wrapper !== name) { - code = code.slice(0, match.index + 2) + wrapper + code.slice(match.index + match[0].length - 1); + code = code.slice(0, astroComponent.index + 2) + wrapper + code.slice(astroComponent.index + astroComponent[0].length - 1); } } collectionItem!.jsx += `,(${code.trim().replace(/\;$/, '')})`; diff --git a/src/compiler/index.ts b/src/compiler/index.ts index 88ea5caf9..541bae21e 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -13,6 +13,7 @@ import { encodeMarkdown } from '../micromark-encode.js'; import { optimize } from './optimize/index.js'; import { codegen } from './codegen.js'; +/** Return Astro internal import URL */ function internalImport(internalPath: string) { return `/_astro_internal/${internalPath}`; } @@ -23,6 +24,13 @@ interface ConvertAstroOptions { fileID: string; } +/** + * .astro -> .jsx + * Core function processing .astro files. Initiates all 3 phases of compilation: + * 1. Parse + * 2. Optimize + * 3. Codegen + */ async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): Promise<TransformResult> { const { filename } = opts; @@ -34,10 +42,14 @@ async function convertAstroToJsx(template: string, opts: ConvertAstroOptions): P // 2. Optimize the AST await optimize(ast, opts); - // Turn AST into JSX + // 3. Turn AST into JSX return await codegen(ast, opts); } +/** + * .md -> .jsx + * Core function processing Markdown, but along the way also calls convertAstroToJsx(). + */ async function convertMdToJsx( contents: string, { compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string } @@ -80,6 +92,7 @@ async function convertMdToJsx( type SupportedExtensions = '.astro' | '.md'; +/** Given a file, process it either as .astro or .md. */ async function transformFromSource( contents: string, { compileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string } @@ -95,6 +108,7 @@ async function transformFromSource( } } +/** Return internal code that gets processed in Snowpack */ export async function compileComponent( source: string, { compileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string } diff --git a/src/compiler/optimize/doctype.ts b/src/compiler/optimize/doctype.ts index fdf6c4078..176880c08 100644 --- a/src/compiler/optimize/doctype.ts +++ b/src/compiler/optimize/doctype.ts @@ -1,5 +1,6 @@ import { Optimizer } from '../../@types/optimizer'; +/** Optimize <!doctype> tg */ export default function (_opts: { filename: string; fileID: string }): Optimizer { let hasDoctype = false; diff --git a/src/compiler/optimize/index.ts b/src/compiler/optimize/index.ts index 53dd3f2d6..a7bf828e0 100644 --- a/src/compiler/optimize/index.ts +++ b/src/compiler/optimize/index.ts @@ -13,6 +13,7 @@ interface VisitorCollection { leave: Map<string, VisitorFn[]>; } +/** Add visitors to given collection */ function addVisitor(visitor: NodeVisitor, collection: VisitorCollection, nodeName: string, event: 'enter' | 'leave') { if (typeof visitor[event] !== 'function') return; if (!collection[event]) collection[event] = new Map<string, VisitorFn[]>(); @@ -22,6 +23,7 @@ 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) { @@ -40,6 +42,7 @@ function collectVisitors(optimizer: Optimizer, htmlVisitors: VisitorCollection, finalizers.push(optimizer.finalize); } +/** Utility for formatting visitors */ function createVisitorCollection() { return { enter: new Map<string, VisitorFn[]>(), @@ -47,6 +50,7 @@ function createVisitorCollection() { }; } +/** Walk AST with collected visitors */ function walkAstWithVisitors(tmpl: TemplateNode, collection: VisitorCollection) { walk(tmpl, { enter(node, parent, key, index) { @@ -68,6 +72,12 @@ function walkAstWithVisitors(tmpl: TemplateNode, collection: VisitorCollection) }); } +/** + * Optimize + * Step 2/3 in Astro SSR. + * Optimize 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) { const htmlVisitors = createVisitorCollection(); const cssVisitors = createVisitorCollection(); diff --git a/src/compiler/optimize/module-scripts.ts b/src/compiler/optimize/module-scripts.ts index 713747fcb..9d4949215 100644 --- a/src/compiler/optimize/module-scripts.ts +++ b/src/compiler/optimize/module-scripts.ts @@ -4,6 +4,7 @@ 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 { const { astroConfig } = compileOptions; const { astroRoot } = astroConfig; diff --git a/src/compiler/optimize/postcss-scoped-styles/index.ts b/src/compiler/optimize/postcss-scoped-styles/index.ts index a4afd99aa..0d1253350 100644 --- a/src/compiler/optimize/postcss-scoped-styles/index.ts +++ b/src/compiler/optimize/postcss-scoped-styles/index.ts @@ -24,15 +24,17 @@ export function scopeSelectors(selector: string, className: string) { let ss = selector; // final output // Pass 1: parse selector string; extract top-level selectors - let start = 0; - let lastValue = ''; - for (let n = 0; n < ss.length; n++) { - const isEnd = n === selector.length - 1; - if (isEnd || CSS_SEPARATORS.has(selector[n])) { - lastValue = selector.substring(start, isEnd ? undefined : n); - if (!lastValue) continue; - selectors.push({ start, end: isEnd ? n + 1 : n, value: lastValue }); - start = n + 1; + { + let start = 0; + let lastValue = ''; + for (let n = 0; n < ss.length; n++) { + const isEnd = n === selector.length - 1; + if (isEnd || CSS_SEPARATORS.has(selector[n])) { + lastValue = selector.substring(start, isEnd ? undefined : n); + if (!lastValue) continue; + selectors.push({ start, end: isEnd ? n + 1 : n, value: lastValue }); + start = n + 1; + } } } diff --git a/src/compiler/optimize/styles.ts b/src/compiler/optimize/styles.ts index b613e4845..36e6f1d7d 100644 --- a/src/compiler/optimize/styles.ts +++ b/src/compiler/optimize/styles.ts @@ -106,7 +106,7 @@ async function transformStyle(code: string, { type, filename, scopedClass, mode return { css, type: styleType }; } -/** Style optimizer */ +/** Optimize <style> tags */ export default function optimizeStyles({ compileOptions, filename, fileID }: OptimizeOptions): Optimizer { const styleNodes: TemplateNode[] = []; // <style> tags to be updated const styleTransformPromises: Promise<StyleTransformResult>[] = []; // async style transform results to be finished in finalize(); |