lvyjs 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/bin/index.js +55 -0
- package/env.d.ts +40 -0
- package/lib/build/get-files.js +26 -0
- package/lib/build/rullup.js +70 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +57 -0
- package/lib/loader/esbuild.js +238 -0
- package/lib/loader/index.d.ts +15 -0
- package/lib/loader/index.js +30 -0
- package/lib/loader/main.d.ts +2 -0
- package/lib/loader/main.js +3 -0
- package/lib/plugins/index.d.ts +27 -0
- package/lib/plugins/index.js +29 -0
- package/lib/plugins/loader-css.js +59 -0
- package/lib/plugins/loader-files.js +38 -0
- package/lib/store.d.ts +40 -0
- package/lib/store.js +39 -0
- package/package.json +80 -0
- package/tsconfig.json +25 -0
package/README.md
ADDED
package/bin/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import { join, dirname, relative } from 'path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
const args = [...process.argv.slice(2)]
|
|
6
|
+
const currentFilePath = fileURLToPath(import.meta.url)
|
|
7
|
+
const currentDirPath = dirname(currentFilePath)
|
|
8
|
+
const pkgFilr = join(currentDirPath, '../package.json')
|
|
9
|
+
// 启动模式
|
|
10
|
+
if (args.includes('start')) {
|
|
11
|
+
const jsFile = join(currentDirPath, '../lib/index.js')
|
|
12
|
+
const jsdir = relative(process.cwd(), jsFile)
|
|
13
|
+
const argsx = args.filter(arg => arg !== 'start')
|
|
14
|
+
const msg = spawn('node', [jsdir, '--lvy-start', ...argsx], {
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
env: Object.assign({}, process.env, {
|
|
17
|
+
PKG_DIR: pkgFilr
|
|
18
|
+
}),
|
|
19
|
+
shell: process.platform === 'win32'
|
|
20
|
+
})
|
|
21
|
+
if (msg.error) {
|
|
22
|
+
console.error(msg.error)
|
|
23
|
+
process.exit()
|
|
24
|
+
}
|
|
25
|
+
} else if (args.includes('build')) {
|
|
26
|
+
const jsFile = join(currentDirPath, '../lib/index.js')
|
|
27
|
+
const jsdir = relative(process.cwd(), jsFile)
|
|
28
|
+
const argsx = args.filter(arg => arg !== 'build')
|
|
29
|
+
const msg = spawn('npx', ['tsx', jsdir, '--lvy-build', ...argsx], {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
env: Object.assign({}, process.env, {
|
|
32
|
+
PKG_DIR: pkgFilr
|
|
33
|
+
}),
|
|
34
|
+
shell: process.platform === 'win32'
|
|
35
|
+
})
|
|
36
|
+
if (msg.error) {
|
|
37
|
+
console.error(msg.error)
|
|
38
|
+
process.exit()
|
|
39
|
+
}
|
|
40
|
+
} else if (args.includes('dev')) {
|
|
41
|
+
const jsFile = join(currentDirPath, '../lib/index.js')
|
|
42
|
+
const jsdir = relative(process.cwd(), jsFile)
|
|
43
|
+
const argsx = args.filter(arg => arg !== 'dev')
|
|
44
|
+
const msg = spawn('npx', ['tsx', 'watch', '--clear-screen=false', jsdir, '--lvy-dev', ...argsx], {
|
|
45
|
+
stdio: 'inherit',
|
|
46
|
+
env: Object.assign({}, process.env, {
|
|
47
|
+
PKG_DIR: pkgFilr
|
|
48
|
+
}),
|
|
49
|
+
shell: process.platform === 'win32'
|
|
50
|
+
})
|
|
51
|
+
if (msg.error) {
|
|
52
|
+
console.error(msg.error)
|
|
53
|
+
process.exit()
|
|
54
|
+
}
|
|
55
|
+
}
|
package/env.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// CSS
|
|
2
|
+
declare module '*.css' {
|
|
3
|
+
const src: string
|
|
4
|
+
export default src
|
|
5
|
+
}
|
|
6
|
+
declare module '*.scss' {
|
|
7
|
+
const src: string
|
|
8
|
+
export default src
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// images
|
|
12
|
+
declare module '*.png' {
|
|
13
|
+
const src: string
|
|
14
|
+
export default src
|
|
15
|
+
}
|
|
16
|
+
declare module '*.jpg' {
|
|
17
|
+
const src: string
|
|
18
|
+
export default src
|
|
19
|
+
}
|
|
20
|
+
declare module '*.jpeg' {
|
|
21
|
+
const src: string
|
|
22
|
+
export default src
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare module '*.gif' {
|
|
26
|
+
const src: string
|
|
27
|
+
export default src
|
|
28
|
+
}
|
|
29
|
+
declare module '*.svg' {
|
|
30
|
+
const src: string
|
|
31
|
+
export default src
|
|
32
|
+
}
|
|
33
|
+
declare module '*.webp' {
|
|
34
|
+
const src: string
|
|
35
|
+
export default src
|
|
36
|
+
}
|
|
37
|
+
declare module '*.ico' {
|
|
38
|
+
const src: string
|
|
39
|
+
export default src
|
|
40
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { readdirSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 获取指定目录下的所有 ts、js、jsx、tsx 文件
|
|
6
|
+
* @param dir 目录路径
|
|
7
|
+
* @returns 文件路径数组
|
|
8
|
+
*/
|
|
9
|
+
const getFiles = (dir) => {
|
|
10
|
+
const results = [];
|
|
11
|
+
const list = readdirSync(dir, { withFileTypes: true });
|
|
12
|
+
list.forEach(item => {
|
|
13
|
+
const fullPath = join(dir, item.name);
|
|
14
|
+
if (item.isDirectory()) {
|
|
15
|
+
results.push(...getFiles(fullPath));
|
|
16
|
+
}
|
|
17
|
+
else if (item.isFile() &&
|
|
18
|
+
/\.(ts|js|jsx|tsx)$/.test(item.name) &&
|
|
19
|
+
!item.name.endsWith('.d.ts')) {
|
|
20
|
+
results.push(fullPath);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return results;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { getFiles };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { rollup } from 'rollup';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import typescript from '@rollup/plugin-typescript';
|
|
4
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
5
|
+
import json from '@rollup/plugin-json';
|
|
6
|
+
import styles from 'rollup-plugin-styles';
|
|
7
|
+
import { runRollupStylesCSSImport } from '../plugins/loader-css.js';
|
|
8
|
+
import { getFiles } from './get-files.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 用于忽略警告
|
|
12
|
+
* @param warning
|
|
13
|
+
* @param warn
|
|
14
|
+
*/
|
|
15
|
+
const onwarn = (warning, warn) => {
|
|
16
|
+
if (warning.code === 'UNRESOLVED_IMPORT')
|
|
17
|
+
return;
|
|
18
|
+
warn(warning);
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param inputs
|
|
23
|
+
* @param output
|
|
24
|
+
*/
|
|
25
|
+
const buildJs = async (inputs, output) => {
|
|
26
|
+
// 从全局变量中,拿到 rollup 的配置
|
|
27
|
+
const plguins = [];
|
|
28
|
+
// 存在build配置
|
|
29
|
+
if (global?.lvyConfig?.build) {
|
|
30
|
+
const p = global.lvyConfig.build?.plugins;
|
|
31
|
+
if (p && Array.isArray(p)) {
|
|
32
|
+
// 遍历插件
|
|
33
|
+
const ps = p.filter(item => item.belong == 'rollup');
|
|
34
|
+
for (const item of ps) {
|
|
35
|
+
plguins.push(item.load());
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const bundle = await rollup({
|
|
40
|
+
input: inputs,
|
|
41
|
+
plugins: [
|
|
42
|
+
...plguins,
|
|
43
|
+
styles({
|
|
44
|
+
mode: ['inject', () => '']
|
|
45
|
+
}),
|
|
46
|
+
runRollupStylesCSSImport(),
|
|
47
|
+
commonjs(),
|
|
48
|
+
json(),
|
|
49
|
+
typescript()
|
|
50
|
+
],
|
|
51
|
+
onwarn: onwarn
|
|
52
|
+
});
|
|
53
|
+
// 写入输出文件
|
|
54
|
+
await bundle.write({
|
|
55
|
+
dir: output,
|
|
56
|
+
format: 'es',
|
|
57
|
+
sourcemap: false,
|
|
58
|
+
preserveModules: true
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
* @param script
|
|
64
|
+
*/
|
|
65
|
+
async function buildAndRun(input, output) {
|
|
66
|
+
const inputFiles = getFiles(join(process.cwd(), input));
|
|
67
|
+
await buildJs(inputFiles, output);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { buildAndRun };
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineConfig } from './store.js';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { buildAndRun } from './build/rullup.js';
|
|
2
|
+
import { initConfig } from './store.js';
|
|
3
|
+
export { defineConfig } from './store.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param input
|
|
7
|
+
*/
|
|
8
|
+
const onDev = async () => {
|
|
9
|
+
const apps = [];
|
|
10
|
+
// 修改config
|
|
11
|
+
for (const plugin of global.lvyConfig.plugins) {
|
|
12
|
+
if (plugin?.config) {
|
|
13
|
+
const cfg = await plugin.config(global.lvyConfig);
|
|
14
|
+
global.lvyConfig = {
|
|
15
|
+
...global.lvyConfig,
|
|
16
|
+
...cfg
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
apps.push(plugin);
|
|
20
|
+
}
|
|
21
|
+
// 执行loader
|
|
22
|
+
await import('./loader/main.js');
|
|
23
|
+
// 执行callback
|
|
24
|
+
for (const app of apps) {
|
|
25
|
+
if (app?.callback)
|
|
26
|
+
await app.callback();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param input
|
|
32
|
+
* @param ouput
|
|
33
|
+
*/
|
|
34
|
+
const onBuild = () => {
|
|
35
|
+
buildAndRun('src', 'lib');
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
const onStart = async () => {
|
|
41
|
+
// 运行模式
|
|
42
|
+
console.log('暂不支持');
|
|
43
|
+
};
|
|
44
|
+
const main = async () => {
|
|
45
|
+
if (process.argv.includes('--lvy-dev')) {
|
|
46
|
+
await initConfig();
|
|
47
|
+
onDev();
|
|
48
|
+
}
|
|
49
|
+
else if (process.argv.includes('--lvy-build')) {
|
|
50
|
+
await initConfig();
|
|
51
|
+
onBuild();
|
|
52
|
+
}
|
|
53
|
+
else if (process.argv.includes('--lvy-start')) {
|
|
54
|
+
onStart();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
main();
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { resolve, relative, dirname, join } from 'path';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import esbuild from 'esbuild';
|
|
5
|
+
import crypto from 'node:crypto';
|
|
6
|
+
|
|
7
|
+
let tsconfig = null;
|
|
8
|
+
let aliases = {};
|
|
9
|
+
const assetsReg = /\.(png|jpg|jpeg|gif|svg|webp|ico)$/;
|
|
10
|
+
const cssReg = /\.(css|scss)$/;
|
|
11
|
+
// 初始化函数,读取并解析 tsconfig.json 文件
|
|
12
|
+
const init = () => {
|
|
13
|
+
try {
|
|
14
|
+
const tsconfigPath = resolve(process.cwd(), 'tsconfig.json');
|
|
15
|
+
if (existsSync(tsconfigPath)) {
|
|
16
|
+
const tsconfigContent = readFileSync(tsconfigPath, 'utf-8');
|
|
17
|
+
tsconfig = JSON.parse(tsconfigContent);
|
|
18
|
+
aliases = tsconfig.compilerOptions?.paths || {};
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
tsconfig = 'error';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
tsconfig = 'error';
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// 初始化配置
|
|
29
|
+
init();
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param input
|
|
33
|
+
* @param output
|
|
34
|
+
*/
|
|
35
|
+
const startCssPost = (input, output) => {
|
|
36
|
+
const run = ['postcss', input, '-o', output, '--watch'];
|
|
37
|
+
// 启动 Tailwind 进程
|
|
38
|
+
const cssPostProcess = spawn('npx', run, {
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
shell: process.platform === 'win32'
|
|
41
|
+
});
|
|
42
|
+
cssPostProcess.on('error', err => {
|
|
43
|
+
console.error('Failed to start Tailwind process:', err);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 生成模块内容
|
|
48
|
+
* @param {string} relativePath 相对路径
|
|
49
|
+
*/
|
|
50
|
+
const generateModuleContent = (relativePath) => {
|
|
51
|
+
const contents = [
|
|
52
|
+
'const createUrl = (basePath, path) => {',
|
|
53
|
+
"const platform = ['linux', 'android', 'darwin'];",
|
|
54
|
+
'const T = platform.includes(process.platform);',
|
|
55
|
+
'const reg = T ? /^file:\\/\\// : /^file:\\/\\/\\//;',
|
|
56
|
+
"return new URL(path, basePath).href.replace(reg, '');",
|
|
57
|
+
'};',
|
|
58
|
+
`const fileUrl = createUrl(import.meta.url, '${relativePath}');`,
|
|
59
|
+
'export default fileUrl;'
|
|
60
|
+
].join('\n');
|
|
61
|
+
return contents;
|
|
62
|
+
};
|
|
63
|
+
const chache = {};
|
|
64
|
+
const getHash = (str) => {
|
|
65
|
+
// 使用 MD5 算法创建哈希对象
|
|
66
|
+
const hash = crypto.createHash('md5');
|
|
67
|
+
// 更新哈希对象内容
|
|
68
|
+
hash.update(str);
|
|
69
|
+
return hash.digest('hex');
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param inputPath
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
const convertPath = (inputPath) => {
|
|
77
|
+
return process.platform === 'win32' ? inputPath.replace(/\\/g, '/') : inputPath;
|
|
78
|
+
};
|
|
79
|
+
const handleAsstesFile = (url) => {
|
|
80
|
+
for (const alias in aliases) {
|
|
81
|
+
const aliasPattern = alias.replace('/*', '');
|
|
82
|
+
if (url.startsWith(aliasPattern)) {
|
|
83
|
+
const aliasPaths = aliases[alias];
|
|
84
|
+
for (const aliasPath of aliasPaths) {
|
|
85
|
+
const fileUrl = join(process.cwd(), aliasPath.replace('/*', ''), url.replace(aliasPattern, ''));
|
|
86
|
+
return `export default "${convertPath(fileUrl)}";`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param param0
|
|
95
|
+
*/
|
|
96
|
+
const esBuildAsstesFule = () => {
|
|
97
|
+
const index = process.argv.indexOf('--import-assets');
|
|
98
|
+
const filter = index != -1 ? new RegExp(process.argv[index + 1]) : assetsReg;
|
|
99
|
+
const namespace = 'assets';
|
|
100
|
+
return {
|
|
101
|
+
name: 'file-loader',
|
|
102
|
+
setup(build) {
|
|
103
|
+
const outputDirs = new Map();
|
|
104
|
+
// 过滤图片文件
|
|
105
|
+
build.onResolve({ filter }, args => {
|
|
106
|
+
const dir = resolve(args.resolveDir, args.path);
|
|
107
|
+
outputDirs.set(dir, args.importer);
|
|
108
|
+
return {
|
|
109
|
+
path: dir,
|
|
110
|
+
namespace
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
build.onLoad({ filter, namespace }, async (args) => {
|
|
114
|
+
if (!outputDirs.has(args.path))
|
|
115
|
+
return null;
|
|
116
|
+
const outputDir = outputDirs.get(args.path);
|
|
117
|
+
const relativePath = relative(dirname(outputDir), args.path);
|
|
118
|
+
// 不管是别名资源。都只是需要返回一个路径
|
|
119
|
+
const aliasResult = handleAsstesFile(relativePath);
|
|
120
|
+
if (aliasResult) {
|
|
121
|
+
return {
|
|
122
|
+
contents: aliasResult,
|
|
123
|
+
loader: 'js'
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
contents: generateModuleContent(relativePath),
|
|
128
|
+
loader: 'js'
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param fileUrl
|
|
137
|
+
* @returns
|
|
138
|
+
*/
|
|
139
|
+
const handleCSS = (fileUrl) => {
|
|
140
|
+
const hash = getHash(fileUrl);
|
|
141
|
+
const outputDir = join(process.cwd(), 'node_modules', 'alemonjs', 'assets', `${hash}.css`);
|
|
142
|
+
if (!chache[fileUrl]) {
|
|
143
|
+
startCssPost(fileUrl, outputDir);
|
|
144
|
+
chache[fileUrl] = true;
|
|
145
|
+
}
|
|
146
|
+
return outputDir;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* 处理路径别名的加载
|
|
150
|
+
* @param {string} url URL
|
|
151
|
+
* @returns {object|null} 加载结果
|
|
152
|
+
*/
|
|
153
|
+
const handleCSSPath = (url) => {
|
|
154
|
+
for (const alias in aliases) {
|
|
155
|
+
const aliasPattern = alias.replace('/*', '');
|
|
156
|
+
if (url.startsWith(aliasPattern)) {
|
|
157
|
+
const aliasPaths = aliases[alias];
|
|
158
|
+
for (const aliasPath of aliasPaths) {
|
|
159
|
+
const fileUrl = join(process.cwd(), aliasPath.replace('/*', ''), url.replace(aliasPattern, ''));
|
|
160
|
+
const outputDir = handleCSS(fileUrl);
|
|
161
|
+
return `export default "${convertPath(outputDir)}";`;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* css资源处理插件
|
|
169
|
+
* @param param0
|
|
170
|
+
* @returns
|
|
171
|
+
*/
|
|
172
|
+
const esBuildCSS = () => {
|
|
173
|
+
const index = process.argv.indexOf('--import-css');
|
|
174
|
+
const filter = index != -1 ? new RegExp(process.argv[index + 1]) : cssReg;
|
|
175
|
+
const namespace = 'css';
|
|
176
|
+
return {
|
|
177
|
+
name: 'css-loader',
|
|
178
|
+
setup(build) {
|
|
179
|
+
const outputDirs = new Map();
|
|
180
|
+
// 过滤 CSS/SCSS 文件
|
|
181
|
+
build.onResolve({ filter }, args => {
|
|
182
|
+
const dir = resolve(args.resolveDir, args.path);
|
|
183
|
+
outputDirs.set(dir, args.importer);
|
|
184
|
+
return {
|
|
185
|
+
path: dir,
|
|
186
|
+
namespace
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
// 加载 CSS/SCSS 文件
|
|
190
|
+
build.onLoad({ filter, namespace }, async (args) => {
|
|
191
|
+
if (!outputDirs.has(args.path))
|
|
192
|
+
return null;
|
|
193
|
+
const outputDir = outputDirs.get(args.path);
|
|
194
|
+
// 计算相对路径
|
|
195
|
+
const relativePath = relative(dirname(outputDir), args.path);
|
|
196
|
+
// 处理路径别名的加载
|
|
197
|
+
const aliasResult = handleCSSPath(relativePath);
|
|
198
|
+
if (aliasResult) {
|
|
199
|
+
return {
|
|
200
|
+
contents: aliasResult,
|
|
201
|
+
loader: 'js'
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// 不是别名资源
|
|
205
|
+
return {
|
|
206
|
+
contents: `export default "${convertPath(handleCSS(args.path))}";`,
|
|
207
|
+
loader: 'js'
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
*
|
|
215
|
+
* @param input
|
|
216
|
+
* @returns
|
|
217
|
+
*/
|
|
218
|
+
const ESBuild = async (input) => {
|
|
219
|
+
const plugins = [];
|
|
220
|
+
if (!process.arch.includes('--no-import-css')) {
|
|
221
|
+
plugins.push(esBuildCSS());
|
|
222
|
+
}
|
|
223
|
+
if (!process.arch.includes('--no-import-assets')) {
|
|
224
|
+
plugins.push(esBuildAsstesFule());
|
|
225
|
+
}
|
|
226
|
+
const result = await esbuild.build({
|
|
227
|
+
entryPoints: [input],
|
|
228
|
+
bundle: true,
|
|
229
|
+
platform: 'node',
|
|
230
|
+
format: 'esm',
|
|
231
|
+
write: false,
|
|
232
|
+
plugins,
|
|
233
|
+
external: ['*']
|
|
234
|
+
});
|
|
235
|
+
return result.outputFiles.map(file => new TextDecoder().decode(file.contents)).join('\n');
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export { ESBuild, esBuildAsstesFule, esBuildCSS };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type LoaderResult = {
|
|
2
|
+
format?: string;
|
|
3
|
+
source?: string;
|
|
4
|
+
shortCircuit?: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param url
|
|
9
|
+
* @param context
|
|
10
|
+
* @param defaultLoad
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
declare const load: (url: string, context: any, defaultLoad: (url: string, context: any) => Promise<LoaderResult>) => Promise<LoaderResult>;
|
|
14
|
+
|
|
15
|
+
export { load };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ESBuild } from './esbuild.js';
|
|
2
|
+
|
|
3
|
+
const platform = ['linux', 'android', 'darwin'];
|
|
4
|
+
const T = platform.includes(process.platform);
|
|
5
|
+
const reg = T ? /^file:\/\// : /^file:\/\/\//;
|
|
6
|
+
const nodeReg = /(node_modules|node_|node:)/;
|
|
7
|
+
const jsReg = /\.(js|ts|jsx|tsx)$/;
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param url
|
|
11
|
+
* @param context
|
|
12
|
+
* @param defaultLoad
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
const load = async (url, context, defaultLoad) => {
|
|
16
|
+
if (nodeReg.test(url)) {
|
|
17
|
+
return defaultLoad(url, context);
|
|
18
|
+
}
|
|
19
|
+
if (!jsReg.test(url)) {
|
|
20
|
+
return defaultLoad(url, context);
|
|
21
|
+
}
|
|
22
|
+
const code = await ESBuild(url.replace(reg, ''));
|
|
23
|
+
return {
|
|
24
|
+
format: 'module',
|
|
25
|
+
source: code,
|
|
26
|
+
shortCircuit: true
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export { load };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as rollup from 'rollup';
|
|
2
|
+
import { RollupAliasOptions } from '@rollup/plugin-alias';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ruleup别名插件
|
|
6
|
+
* @param options
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
declare const alias: (options?: RollupAliasOptions) => {
|
|
10
|
+
belong: "rollup" | "esbuild" | "other";
|
|
11
|
+
name: string;
|
|
12
|
+
load: () => rollup.Plugin<any>;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* ruleup插件:对指定类型文件进行字符串引用处理
|
|
16
|
+
* @param options
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
declare const files: (options: {
|
|
20
|
+
filter: RegExp;
|
|
21
|
+
}) => {
|
|
22
|
+
belong: "rollup" | "esbuild" | "other";
|
|
23
|
+
name: string;
|
|
24
|
+
load: () => rollup.InputPluginOption;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { alias, files };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import aliasx from '@rollup/plugin-alias';
|
|
2
|
+
import { rollupNodeFiles } from './loader-files.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ruleup别名插件
|
|
6
|
+
* @param options
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
const alias = (options) => {
|
|
10
|
+
return {
|
|
11
|
+
belong: 'rollup',
|
|
12
|
+
name: 'alias',
|
|
13
|
+
load: () => aliasx(options)
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* ruleup插件:对指定类型文件进行字符串引用处理
|
|
18
|
+
* @param options
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
const files = (options) => {
|
|
22
|
+
return {
|
|
23
|
+
belong: 'rollup',
|
|
24
|
+
name: 'import-files',
|
|
25
|
+
load: () => rollupNodeFiles(options)
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { alias, files };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
2
|
+
import { resolve, dirname, basename } from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
const runRollupStylesCSSImport = () => {
|
|
9
|
+
const { include = /\.(css|scss)$/i } = {};
|
|
10
|
+
const filter = createFilter(include, null);
|
|
11
|
+
return {
|
|
12
|
+
name: 'c-css',
|
|
13
|
+
resolveId(source, importer) {
|
|
14
|
+
if (filter(source)) {
|
|
15
|
+
return resolve(dirname(importer), source);
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
load(id) {
|
|
19
|
+
if (filter(id))
|
|
20
|
+
this.addWatchFile(resolve(id));
|
|
21
|
+
return null;
|
|
22
|
+
},
|
|
23
|
+
async transform(code, id) {
|
|
24
|
+
if (!filter(id))
|
|
25
|
+
return null;
|
|
26
|
+
// 删除 export default css
|
|
27
|
+
const codex = code.replace(/(export|default css)/g, '');
|
|
28
|
+
// 使用 eval 执行代码并获取默认导出的值
|
|
29
|
+
const evalCode = `
|
|
30
|
+
(() => {
|
|
31
|
+
${codex}
|
|
32
|
+
return css;
|
|
33
|
+
})()
|
|
34
|
+
`;
|
|
35
|
+
// 得到css变量的值
|
|
36
|
+
const csscode = eval(evalCode);
|
|
37
|
+
// 确保最后生产的css文件
|
|
38
|
+
const refeId = this.emitFile({
|
|
39
|
+
// 属于静态资源
|
|
40
|
+
type: 'asset',
|
|
41
|
+
name: basename(`${id}.css`),
|
|
42
|
+
// 内容
|
|
43
|
+
source: csscode
|
|
44
|
+
});
|
|
45
|
+
const contents = `
|
|
46
|
+
const createUrl = () => {
|
|
47
|
+
const platform = ['linux', 'android', 'darwin'];
|
|
48
|
+
const T = platform.includes(process.platform);
|
|
49
|
+
const reg = T ? /^file:\\/\\// : /^file:\\/\\/\\//
|
|
50
|
+
return import.meta.ROLLUP_FILE_URL_${refeId}.replace(reg, '')
|
|
51
|
+
};
|
|
52
|
+
export default createUrl();
|
|
53
|
+
`;
|
|
54
|
+
return contents;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { runRollupStylesCSSImport };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { resolve, dirname, basename } from 'path';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {Object} options
|
|
6
|
+
* @returns {Object}
|
|
7
|
+
*/
|
|
8
|
+
const rollupNodeFiles = ({ filter }) => {
|
|
9
|
+
return {
|
|
10
|
+
name: 'rollup-node-files',
|
|
11
|
+
resolveId(source, importer) {
|
|
12
|
+
if (filter.test(source)) {
|
|
13
|
+
return resolve(dirname(importer), source);
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
load(id) {
|
|
17
|
+
if (filter.test(id)) {
|
|
18
|
+
const referenceId = this.emitFile({
|
|
19
|
+
type: 'asset',
|
|
20
|
+
name: basename(id),
|
|
21
|
+
source: readFileSync(id)
|
|
22
|
+
});
|
|
23
|
+
const content = [
|
|
24
|
+
'const createUrl = () => {',
|
|
25
|
+
"const platform = ['linux', 'android', 'darwin'];",
|
|
26
|
+
'const T = platform.includes(process.platform);',
|
|
27
|
+
'const reg = T ? /^file:\\/\\// : /^file:\\/\\/\\//',
|
|
28
|
+
'return import.meta.ROLLUP_FILE_URL_' + referenceId + ".replace(reg, '')",
|
|
29
|
+
'};',
|
|
30
|
+
'export default createUrl();'
|
|
31
|
+
].join('\n');
|
|
32
|
+
return content;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { rollupNodeFiles };
|
package/lib/store.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { RollupOptions } from 'rollup';
|
|
2
|
+
|
|
3
|
+
type Options = {
|
|
4
|
+
plugins?: {
|
|
5
|
+
name: string;
|
|
6
|
+
/**
|
|
7
|
+
* ⚠️直接optoins进行调整
|
|
8
|
+
* @param options
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
config: (options: Options) => Options;
|
|
12
|
+
/**
|
|
13
|
+
* 执行
|
|
14
|
+
*/
|
|
15
|
+
callback?: () => void;
|
|
16
|
+
}[];
|
|
17
|
+
build?: {
|
|
18
|
+
plugins?: {
|
|
19
|
+
belong: 'rollup' | 'esbuild' | 'other';
|
|
20
|
+
name: string;
|
|
21
|
+
load: any;
|
|
22
|
+
}[];
|
|
23
|
+
rollupOptions?: {
|
|
24
|
+
input?: string | string[];
|
|
25
|
+
} & RollupOptions;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
declare global {
|
|
32
|
+
var lvyConfig: Options;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @param param0
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
declare const defineConfig: (optoins?: Options) => Options;
|
|
39
|
+
|
|
40
|
+
export { type Options, defineConfig };
|
package/lib/store.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
const initConfig = async () => {
|
|
8
|
+
if (!global.lvyConfig) {
|
|
9
|
+
// init
|
|
10
|
+
global.lvyConfig = {};
|
|
11
|
+
}
|
|
12
|
+
const files = [
|
|
13
|
+
'lvy.config.ts',
|
|
14
|
+
'lvy.config.js',
|
|
15
|
+
'lvy.config.mjs',
|
|
16
|
+
'lvy.config.cjs',
|
|
17
|
+
'lvy.config.tsx'
|
|
18
|
+
];
|
|
19
|
+
let configDir = '';
|
|
20
|
+
for (const file of files) {
|
|
21
|
+
if (existsSync(file)) {
|
|
22
|
+
configDir = file;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (configDir !== '') {
|
|
27
|
+
const v = await import(`file://${join(process.cwd(), configDir)}`);
|
|
28
|
+
if (v?.default) {
|
|
29
|
+
global.lvyConfig = v.default;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* @param param0
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
const defineConfig = (optoins) => optoins;
|
|
38
|
+
|
|
39
|
+
export { defineConfig, initConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lvyjs",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "tsx compile script",
|
|
5
|
+
"author": "lemonade",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@rollup/plugin-alias": "^5.1.0",
|
|
11
|
+
"@rollup/plugin-commonjs": "^28.0.0",
|
|
12
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
13
|
+
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
14
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
15
|
+
"autoprefixer": "^10.4.20",
|
|
16
|
+
"cssnano": "^7.0.6",
|
|
17
|
+
"esbuild": "^0.24.0",
|
|
18
|
+
"logger": "^0.0.1",
|
|
19
|
+
"postcss": "^8.4.47",
|
|
20
|
+
"postcss-cli": "^11.0.0",
|
|
21
|
+
"postcss-import": "^16.1.0",
|
|
22
|
+
"postcss-nested": "^6.2.0",
|
|
23
|
+
"postcss-sass": "^0.5.0",
|
|
24
|
+
"postcss-scss": "^4.0.9",
|
|
25
|
+
"postcss-simple-vars": "^7.0.1",
|
|
26
|
+
"postcss-styled": "^0.34.0",
|
|
27
|
+
"postcss-syntax": "^0.36.2",
|
|
28
|
+
"postcss-url": "^10.1.3",
|
|
29
|
+
"rollup": "^4.18.1",
|
|
30
|
+
"rollup-plugin-dts": "^6.1.1",
|
|
31
|
+
"rollup-plugin-styles": "^4.0.0",
|
|
32
|
+
"sass": "^1.79.4",
|
|
33
|
+
"tailwindcss": "^3.4.3",
|
|
34
|
+
"tsx": "^4.19.1",
|
|
35
|
+
"typescript": "^5.5.3"
|
|
36
|
+
},
|
|
37
|
+
"types": "lib",
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"import": "./lib/index.js",
|
|
41
|
+
"types": "./lib/index.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./loader": {
|
|
44
|
+
"import": "./lib/loader/index.js",
|
|
45
|
+
"types": "./lib/loader/index.d.ts"
|
|
46
|
+
},
|
|
47
|
+
"./register": {
|
|
48
|
+
"import": "./lib/loader/main.js",
|
|
49
|
+
"types": "./lib/loader/main.d.ts"
|
|
50
|
+
},
|
|
51
|
+
"./env": {
|
|
52
|
+
"types": "./env.d.ts"
|
|
53
|
+
},
|
|
54
|
+
"./plugins": {
|
|
55
|
+
"import": "./lib/plugins/index.js",
|
|
56
|
+
"types": "./lib/plugins/index.d.ts"
|
|
57
|
+
},
|
|
58
|
+
"./tsconfig.json": {
|
|
59
|
+
"import": "./tsconfig.json",
|
|
60
|
+
"types": "./tsconfig.json"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"bin": {
|
|
64
|
+
"lvy": "bin/index.js"
|
|
65
|
+
},
|
|
66
|
+
"keywords": [
|
|
67
|
+
"ts",
|
|
68
|
+
"tsx",
|
|
69
|
+
"react"
|
|
70
|
+
],
|
|
71
|
+
"publishConfig": {
|
|
72
|
+
"registry": "https://registry.npmjs.org",
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"bugs": "https://github.com/ningmengchongshui/alemonjs/issues",
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "https://github.com/ningmengchongshui/alemonjs.git"
|
|
79
|
+
}
|
|
80
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// model
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
// jsx
|
|
10
|
+
"jsx": "react",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"noEmit": true,
|
|
14
|
+
// version
|
|
15
|
+
"ignoreDeprecations": "5.0",
|
|
16
|
+
// strict
|
|
17
|
+
"noImplicitAny": false,
|
|
18
|
+
"useDefineForClassFields": true,
|
|
19
|
+
"isolatedModules": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"forceConsistentCasingInFileNames": true
|
|
24
|
+
}
|
|
25
|
+
}
|