summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/codegen.ts24
-rw-r--r--src/compiler/index.ts16
-rw-r--r--src/compiler/optimize/doctype.ts1
-rw-r--r--src/compiler/optimize/index.ts10
-rw-r--r--src/compiler/optimize/module-scripts.ts1
-rw-r--r--src/compiler/optimize/postcss-scoped-styles/index.ts20
-rw-r--r--src/compiler/optimize/styles.ts2
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();