Skip to content

Commit

Permalink
feat: 添加 AppRouter 编译器
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Apr 17, 2024
1 parent d6c1e46 commit 9ea5641
Show file tree
Hide file tree
Showing 14 changed files with 465 additions and 138 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ typings/
test/fixtures/*/project
*.zip
.vscode
lib/app-plugin
4 changes: 2 additions & 2 deletions lib/compiler/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path";
import UIPlugin from "./ui-plugin.js";
import AppPlugin from "../app-plugin/index.js";

export default {
module: {
Expand Down Expand Up @@ -70,6 +70,6 @@ export default {
extensions: [".ts", ".tsx", ".mjs", ".js", ".jsx"],
},
plugins: [
new UIPlugin()
new AppPlugin()
]
};
34 changes: 17 additions & 17 deletions lib/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ function getDirs() {
};
return {
rootContext,
appDirPath: mkdir(path.join(rootContext, "app")),
buildDirPath: mkdir(path.join(rootContext, ".lcui/build")),
sourceDirPath: mkdir(path.join(rootContext, "src")),
modulesDirPath: path.join(rootContext, "node_modules"),
modulesOutputDirPath: mkdir(path.join(rootContext, "vendor.node_modules")),
distDir: mkdir(path.join(rootContext, "dist")),
buildDir: mkdir(path.join(rootContext, ".lcui/build")),
appDir: mkdir(path.join(rootContext, "app")),
modulesDir: path.join(rootContext, "node_modules"),
modulesOutputDir: mkdir(path.join(rootContext, "vendor.node_modules")),
};
}

Expand Down Expand Up @@ -101,7 +101,7 @@ function resolveModuleImportPath(name, context) {
if (!dir || !ext) {
return name;
}
return path.join(context.modulesDirPath, name);
return path.join(context.modulesDir, name);
}
return path.resolve(context.context, name);
}
Expand All @@ -119,7 +119,7 @@ function resolveModuleOutputPath(name, context) {
if (!dir || !ext) {
return name;
}
fullPath = path.join(context.modulesDirPath, name);
fullPath = path.join(context.modulesDir, name);
} else {
fullPath = path.resolve(context.context, name);
}
Expand All @@ -129,17 +129,17 @@ function resolveModuleOutputPath(name, context) {
if (!resolvedPath) {
throw new Error(`${name}: File does not exist`);
}
const modulesPath = path.join(context.buildDirPath, "node_modules");
const modulesPath = path.join(context.buildDir, "node_modules");
const outputPath = resolveModuleExt(
path.join(
context.buildDirPath,
context.buildDir,
path.relative(context.rootContext, resolvedPath)
)
);
// 更改路径,避免 import 语句中的模块路径被解析到构建目录中的 node_modules
if (outputPath.startsWith(modulesPath)) {
return path.join(
context.buildDirPath,
context.buildDir,
"[modules]",
outputPath.substring(modulesPath.length)
);
Expand Down Expand Up @@ -181,7 +181,7 @@ export default async function compile(file, compilerOptions) {
...getDirs(),
...compilerOptions,
};
const logFile = path.join(options.buildDirPath, "compile.log");
const logFile = path.join(options.buildDir, "compile.log");
const logger = createLogger(logFile, options.verbose);

function createHook() {
Expand Down Expand Up @@ -251,7 +251,7 @@ export default async function compile(file, compilerOptions) {
return cache;
}
if (
outputDirPath.startsWith(context.buildDirPath) &&
outputDirPath.startsWith(context.buildDir) &&
!fs.existsSync(outputDirPath)
) {
fs.mkdirpSync(outputDirPath);
Expand Down Expand Up @@ -372,10 +372,10 @@ export default async function compile(file, compilerOptions) {

function createCompilerContext(resourcePath) {
let outputPath = resourcePath;
if (resourcePath.startsWith(options.modulesDirPath)) {
if (resourcePath.startsWith(options.modulesDir)) {
outputPath = path.join(
options.modulesOutputDirPath,
resourcePath.substring(options.modulesDirPath.length + 1)
options.modulesOutputDir,
resourcePath.substring(options.modulesDir.length + 1)
);
if (!fs.existsSync(path.dirname(outputPath))) {
fs.mkdirpSync(path.dirname(outputPath));
Expand All @@ -389,7 +389,7 @@ export default async function compile(file, compilerOptions) {
resourceOutputPath: `${outputPath}.h`,
context: path.dirname(resourcePath),
emitFile(name, content) {
const outputPath = path.resolve(options.appDirPath, name);
const outputPath = path.resolve(options.distDir, name);
const outputDir = path.dirname(outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirpSync(outputDir);
Expand All @@ -401,7 +401,7 @@ export default async function compile(file, compilerOptions) {
printError(resourcePath, error);
},
resolveOutput(name) {
// TODO: 引入项目目录外的文件时,将路径转换成 buildDirPath
// TODO: 引入项目目录外的文件时,将路径转换成 buildDir
return path.resolve(context.context, `${name}.h`);
},
resolveModule(name) {
Expand Down
4 changes: 2 additions & 2 deletions lib/compiler/ts-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default async function TsLoader(content) {
.slice(1, -1);
let modulePath = loader.resolveModule(importPath);
modules.push(loader.importModule(importPath));
if (modulePath.startsWith(loader.buildDirPath)) {
if (modulePath.startsWith(loader.buildDir)) {
modulePath = path.relative(outputDirPath, modulePath);
modulePath = `.${path.sep}${modulePath}`;
}
Expand Down Expand Up @@ -74,7 +74,7 @@ export default async function TsLoader(content) {

const { compile } = await import(
`file://${path.join(
loader.modulesDirPath,
loader.modulesDir,
"@lcui",
"react",
"lib",
Expand Down
92 changes: 0 additions & 92 deletions lib/compiler/ui-plugin.js

This file was deleted.

105 changes: 105 additions & 0 deletions lib/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/// <reference types="node" resolution-mode="require"/>
export interface ModuleMetadata {
type: "javascript" | "asset";
/** 资源文件所在路径 */
path: string;
/** 资源文件输出路径 */
outputPath: string;
/** 加载该资源时需要包含的 C 头文件 */
headerFiles: string[];
/**
* 初始化代码
* 加载该资源所需要执行的 C 代码
**/
initCode: string;
}
export interface Module extends Record<string, any> {
default: any;
metadata: ModuleMetadata;
}
export interface CompilerOptions {
verbose?: boolean;
/**
* 模块所在的目录
* 可以用作解析其他模块成员的上下文
**/
context: string;
/** 根目录 */
rootContext: string;
distDir: string;
appDir: string;
buildDir: string;
modulesDir: string;
modulesOutputDir: string;
}
export interface Hook<T = (...args: any[]) => any> {
tap(name: string, fn: T): void;
call: T;
}
export interface CompilerContext extends CompilerOptions {
/** 资源文件的路径 */
resourcePath: string;
/** 资源文件的输出路径 */
resourceOutputPath: string;
emitError(err: Error): void;
/** 确定资源文件的输出路径 */
resolveOutput(name: string): string;
/** 确定资源文件的模块路径 */
resolveModule(name: string): string;
/** 引入与资源文件对应的模块 */
importModule(name: string): Promise<Module>;
/** 输出文件 */
emitFile(name: string, content: string | Buffer): void;
/** 生成模块 */
generateModule(name: string, generator: () => Promise<string | Buffer>): Promise<void>;
logger: import("winston").Logger;
}
export interface LoaderContext extends CompilerContext {
data: Record<string, any>;
/** 获取配置选项 */
getOptions(): any;
}
export interface CompilerInstance {
options: CompilerOptions;
logger: import("winston").Logger;
hooks: {
loadModule: Hook<(file: string, data: Record<string, any>) => void>;
done: Hook;
};
}
export interface ComponentConfig {
headerFilePath: string;
resourceLoaderName: string;
assets: Module[];
components: string[];
}
export interface ResourceNode {
name: string;
text?: string;
attributes?: Record<string, any>;
children?: ResourceNode[];
}
type LoaderOptions = Record<string, any>;
export interface UILoaderOptions extends LoaderOptions {
indent?: number;
}
type LoaderInput = string | Buffer | ResourceNode;
type Loader = (this: LoaderContext, content: LoaderInput) => LoaderInput | Promise<undefined>;
type LoaderRule = {
loader: string | Loader;
options: LoaderOptions;
};
type ModuleRuleUseConfig = string | (LoaderRule | string)[];
export interface ModuleRule {
test: RegExp | ((path: string) => boolean);
use: ModuleRuleUseConfig;
}
export interface ModuleCacheItem {
state: "pending" | "loading" | "loaded";
outputPath: string;
exports: Promise<Module>;
resolve: (exports: Module) => void;
reject: (err: Error) => void;
}
export type ModuleCacheMap = Record<string, ModuleCacheItem>;
export {};
1 change: 1 addition & 0 deletions lib/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"bin": {
"lcui": "bin/lcui.js"
},
"types": "./lib/types.d.ts",
"scripts": {
"test": "nyc mocha",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
Expand Down Expand Up @@ -37,14 +38,16 @@
"react-dom": "^18.2.0",
"sass": "^1.64.2",
"simple-git": "^3.3.0",
"typescript": "^5.1.6",
"typescript": "^5.4.5",
"winston": "^3.10.0",
"xml-js": "^1.6.11",
"yaml": "^2.3.1"
},
"devDependencies": {
"@commitlint/cli": "^12.1.1",
"@commitlint/config-conventional": "^12.1.1",
"@types/fs-extra": "^11.0.4",
"@types/react": "^18.2.64",
"codecov": "^3.8.2",
"eslint": "^8.50.0",
"husky": "^6.0.0",
Expand Down
Loading

0 comments on commit 9ea5641

Please sign in to comment.