Skip to content

Commit

Permalink
Annoying Lint PR #2 (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
drwpow committed Apr 1, 2021
1 parent f6a7ac6 commit c26c244
Show file tree
Hide file tree
Showing 32 changed files with 156 additions and 49 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/parser/parse/**/*.ts
7 changes: 4 additions & 3 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ module.exports = {
'@typescript-eslint/ban-ts-comment': 'warn',
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-empty-function': 'off',
'no-shadow': 'warn',
'prettier/prettier': 'error',
'no-shadow': 'error',
'prefer-const': 'off',
'prefer-rest-params': 'off',
'require-jsdoc': 'warn',
Expand Down
3 changes: 3 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@ import type { Attribute } from './parser/interfaces';

// AST utility functions

/** Get TemplateNode attribute from name */
export function getAttr(attributes: Attribute[], name: string): Attribute | undefined {
const attr = attributes.find((a) => a.name === name);
return attr;
}

/** Get TemplateNode attribute by value */
export function getAttrValue(attributes: Attribute[], name: string): string | undefined {
const attr = getAttr(attributes, name);
if (attr) {
return attr.value[0]?.data;
}
}

/** Set TemplateNode attribute value */
export function setAttrValue(attributes: Attribute[], name: string, value: string): void {
const attr = attributes.find((a) => a.name === name);
if (attr) {
Expand Down
5 changes: 5 additions & 0 deletions src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const logging: LogOptions = {
dest: defaultLogDestination,
};

/** Return contents of astro/pages */
async function allPages(root: URL) {
const api = new fdir()
.filter((p) => /\.(astro|md)$/.test(p))
Expand All @@ -26,19 +27,22 @@ async function allPages(root: URL) {
return files as string[];
}

/** Utility for merging two Set()s */
function mergeSet(a: Set<string>, b: Set<string>) {
for (let str of b) {
a.add(str);
}
return a;
}

/** Utility for writing to file (async) */
async function writeFilep(outPath: URL, bytes: string | Buffer, encoding: 'utf-8' | null) {
const outFolder = new URL('./', outPath);
await mkdir(outFolder, { recursive: true });
await writeFile(outPath, bytes, encoding || 'binary');
}

/** Utility for writing a build result to disk */
async function writeResult(result: LoadResult, outPath: URL, encoding: null | 'utf-8') {
if (result.statusCode !== 200) {
error(logging, 'build', result.error || result.statusCode);
Expand All @@ -49,6 +53,7 @@ async function writeResult(result: LoadResult, outPath: URL, encoding: null | 'u
}
}

/** The primary build action */
export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
const { projectRoot, astroRoot } = astroConfig;
const pageRoot = new URL('./pages/', astroRoot);
Expand Down
19 changes: 12 additions & 7 deletions src/build/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import esbuild from 'esbuild';
import { promises as fsPromises } from 'fs';
import { parse } from '../parser/index.js';
import { optimize } from '../compiler/optimize/index.js';
import { getAttrValue, setAttrValue } from '../ast.js';
import { getAttrValue } from '../ast.js';
import { walk } from 'estree-walker';
import babelParser from '@babel/parser';
import path from 'path';
Expand All @@ -20,6 +20,7 @@ const { readFile } = fsPromises;

type DynamicImportMap = Map<'vue' | 'react' | 'react-dom' | 'preact', string>;

/** Add framework runtimes when needed */
async function acquireDynamicComponentImports(plugins: Set<ValidExtensionPlugins>, resolve: (s: string) => Promise<string>): Promise<DynamicImportMap> {
const importMap: DynamicImportMap = new Map();
for (let plugin of plugins) {
Expand All @@ -42,6 +43,7 @@ async function acquireDynamicComponentImports(plugins: Set<ValidExtensionPlugins
return importMap;
}

/** Evaluate mustache expression (safely) */
function compileExpressionSafe(raw: string): string {
let { code } = transformSync(raw, {
loader: 'tsx',
Expand All @@ -65,6 +67,7 @@ interface CollectDynamic {
mode: RuntimeMode;
}

/** Gather necessary framework runtimes for dynamic components */
export async function collectDynamicImports(filename: URL, { astroConfig, logging, resolve, mode }: CollectDynamic) {
const imports = new Set<string>();

Expand Down Expand Up @@ -127,7 +130,8 @@ export async function collectDynamicImports(filename: URL, { astroConfig, loggin

const dynamic = await acquireDynamicComponentImports(plugins, resolve);

function appendImports(rawName: string, filename: URL, astroConfig: AstroConfig) {
/** Add dynamic component runtimes to imports */
function appendImports(rawName: string, importUrl: URL) {
const [componentName, componentType] = rawName.split(':');
if (!componentType) {
return;
Expand All @@ -138,7 +142,7 @@ export async function collectDynamicImports(filename: URL, { astroConfig, loggin
}

const defn = components[componentName];
const fileUrl = new URL(defn.specifier, filename);
const fileUrl = new URL(defn.specifier, importUrl);
let rel = path.posix.relative(astroConfig.astroRoot.pathname, fileUrl.pathname);

switch (defn.plugin) {
Expand Down Expand Up @@ -193,15 +197,15 @@ export async function collectDynamicImports(filename: URL, { astroConfig, loggin
while ((match = regex.exec(code))) {
matches.push(match);
}
for (const match of matches.reverse()) {
const name = match[1];
appendImports(name, filename, astroConfig);
for (const foundImport of matches.reverse()) {
const name = foundImport[1];
appendImports(name, filename);
}
break;
}
case 'InlineComponent': {
if (/^[A-Z]/.test(node.name)) {
appendImports(node.name, filename, astroConfig);
appendImports(node.name, filename);
return;
}

Expand All @@ -220,6 +224,7 @@ interface BundleOptions {
astroConfig: AstroConfig;
}

/** The primary bundling/optimization action */
export async function bundle(imports: Set<string>, { runtime, dist }: BundleOptions) {
const ROOT = 'astro:root';
const root = `
Expand Down
1 change: 1 addition & 0 deletions src/build/static.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Element } from 'domhandler';
import cheerio from 'cheerio';

/** Given an HTML string, collect <link> and <img> tags */
export function collectStatics(html: string) {
const statics = new Set<string>();

Expand Down
5 changes: 5 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const buildAndExit = async (...args: Parameters<typeof build>) => {
type Arguments = yargs.Arguments;
type cliState = 'help' | 'version' | 'dev' | 'build';

/** Determine which action the user requested */
function resolveArgs(flags: Arguments): cliState {
if (flags.version) {
return 'version';
Expand All @@ -35,6 +36,7 @@ function resolveArgs(flags: Arguments): cliState {
}
}

/** Display --help flag */
function printHelp() {
console.error(` ${colors.bold('astro')} - Futuristic web development tool.
Expand All @@ -48,11 +50,13 @@ function printHelp() {
`);
}

/** Display --version flag */
async function printVersion() {
const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf-8'));
console.error(pkg.version);
}

/** Handle `astro run` command */
async function runCommand(rawRoot: string, cmd: (a: AstroConfig) => Promise<void>) {
const astroConfig = await loadConfig(rawRoot);
if (typeof astroConfig === 'undefined') {
Expand All @@ -69,6 +73,7 @@ const cmdMap = new Map([
['dev', devServer],
]);

/** The primary CLI action */
export async function cli(args: string[]) {
const flags = yargs(args);
const state = resolveArgs(flags);
Expand Down
24 changes: 20 additions & 4 deletions src/compiler/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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',
Expand All @@ -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) {
Expand All @@ -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;

Expand Down Expand Up @@ -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}`);
Expand All @@ -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(/\;$/, '')})`;
Expand Down
16 changes: 15 additions & 1 deletion src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
}
Expand All @@ -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;

Expand All @@ -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 }
Expand Down Expand Up @@ -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 }
Expand All @@ -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 }
Expand Down
1 change: 1 addition & 0 deletions src/compiler/optimize/doctype.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Optimizer } from '../../@types/optimizer';

/** Optimize <!doctype> tg */
export default function (_opts: { filename: string; fileID: string }): Optimizer {
let hasDoctype = false;

Expand Down
Loading

0 comments on commit c26c244

Please sign in to comment.