lvyjs 0.2.1 → 0.2.3

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 CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  一款为 node 构建的开发工具
4
4
 
5
- https://github.com/lemonade-lab/lvyjs
5
+ https://github.com/lvyjs/core
package/bin/index.js CHANGED
@@ -7,18 +7,21 @@ const args = [...process.argv.slice(2)]
7
7
  const currentFilePath = fileURLToPath(import.meta.url)
8
8
  const currentDirPath = dirname(currentFilePath)
9
9
  const pkgFilr = join(currentDirPath, '../package.json')
10
+
11
+ const jsFile = join(currentDirPath, '../lib/index.js')
12
+ const jsdir = relative(process.cwd(), jsFile)
13
+
14
+ let tsxDir = join(currentDirPath, '../../tsx/dist/cli.mjs')
15
+ if (!existsSync(tsxDir)) {
16
+ tsxDir = join(currentDirPath, '../node_modules/tsx/dist/cli.mjs')
17
+ }
18
+ if (!existsSync(tsxDir)) {
19
+ tsxDir = join(process.cwd(), 'node_modules/tsx/dist/cli.mjs')
20
+ }
21
+
10
22
  // 启动模式
11
23
  if (args.includes('build')) {
12
- const jsFile = join(currentDirPath, '../lib/index.js')
13
- const jsdir = relative(process.cwd(), jsFile)
14
24
  const argsx = args.filter(arg => arg !== 'build')
15
- let tsxDir = join(currentDirPath, '../../tsx/dist/cli.mjs')
16
- if (!existsSync(tsxDir)) {
17
- tsxDir = join(currentDirPath, '../node_modules/tsx/dist/cli.mjs')
18
- }
19
- if (!existsSync(tsxDir)) {
20
- tsxDir = join(process.cwd(), 'node_modules/tsx/dist/cli.mjs')
21
- }
22
25
  const msg = fork(tsxDir, [jsdir, '--lvy-build', ...argsx], {
23
26
  stdio: 'inherit',
24
27
  env: Object.assign({}, process.env, {
@@ -31,21 +34,13 @@ if (args.includes('build')) {
31
34
  process.exit()
32
35
  }
33
36
  } else if (args.includes('dev')) {
34
- const jsFile = join(currentDirPath, '../lib/index.js')
35
- const jsdir = relative(process.cwd(), jsFile)
36
37
  const argsx = args.filter(arg => arg !== 'dev')
37
38
  const argv = [
38
- ...(args.includes('--no-watch') ? [] : ['watch', '--clear-screen=false']),
39
+ args.includes('--no-watch') ? '' : 'watch',
40
+ '--clear-screen=false',
39
41
  jsdir,
40
42
  '--lvy-dev'
41
43
  ]
42
- let tsxDir = join(currentDirPath, '../../tsx/dist/cli.mjs')
43
- if (!existsSync(tsxDir)) {
44
- tsxDir = join(currentDirPath, '../node_modules/tsx/dist/cli.mjs')
45
- }
46
- if (!existsSync(tsxDir)) {
47
- tsxDir = join(process.cwd(), 'node_modules/tsx/dist/cli.mjs')
48
- }
49
44
  const msg = fork(tsxDir, [...argv, ...argsx], {
50
45
  stdio: 'inherit',
51
46
  env: Object.assign({}, process.env, {
@@ -1,4 +1,4 @@
1
1
  const assetsReg = /\.(png|jpg|jpeg|gif|svg|webp|ico)$/;
2
- const cssReg = /\.(css|scss)$/;
2
+ const cssReg = /\.(css|scss|less|sass|less)$/;
3
3
 
4
4
  export { assetsReg, cssReg };
@@ -0,0 +1,8 @@
1
+ /**
2
+ *
3
+ * @param input
4
+ * @returns
5
+ */
6
+ declare const ESBuild: (input: string) => Promise<string>;
7
+
8
+ export { ESBuild };
@@ -1,5 +1,7 @@
1
1
  import esbuild from 'esbuild';
2
- import { esBuildAlias, esBuildAsstes, esBuildCSS } from './plugins.js';
2
+ import { esBuildCSS } from './plugins/css.js';
3
+ import { esBuildAlias } from './plugins/alias.js';
4
+ import { esBuildAsstes } from './plugins/Asstes.js';
3
5
 
4
6
  // 插件
5
7
  const plugins = [];
@@ -7,11 +9,14 @@ const plugins = [];
7
9
  *
8
10
  */
9
11
  const initPlugins = () => {
10
- if (global.lvyConfig?.assets) {
12
+ if (typeof global.lvyConfig?.alias != 'boolean') {
13
+ plugins.push(esBuildAlias(global.lvyConfig.alias));
14
+ }
15
+ if (typeof global.lvyConfig?.assets != 'boolean') {
11
16
  plugins.push(esBuildAsstes(global.lvyConfig.assets));
12
17
  }
13
- if (typeof global.lvyConfig?.esbuild?.styles != 'boolean') {
14
- plugins.push(esBuildCSS(global.lvyConfig.esbuild?.styles));
18
+ if (typeof global.lvyConfig?.styles != 'boolean') {
19
+ plugins.push(esBuildCSS(global.lvyConfig?.styles ?? {}));
15
20
  }
16
21
  };
17
22
  /**
@@ -25,16 +30,13 @@ const ESBuild = async (input) => {
25
30
  global.lvyConfig = {};
26
31
  if (!global.lvyConfig.esbuild)
27
32
  global.lvyConfig.esbuild = {};
28
- // alias
29
- if (global.lvyConfig.alias)
30
- esBuildAlias(global.lvyConfig.alias);
31
33
  // 没有插件时,检查是否有可用插件。
32
34
  if (plugins.length === 0) {
33
35
  // init plugisn
34
36
  await initPlugins();
35
37
  }
36
- //
37
- const options = global.lvyConfig?.esBuildOptions || {};
38
+ const options = global.lvyConfig?.esbuild?.options ?? {};
39
+ const pl = options?.plugins ?? [];
38
40
  // 构建
39
41
  const result = await esbuild.build({
40
42
  // 入口文件
@@ -47,10 +49,10 @@ const ESBuild = async (input) => {
47
49
  format: 'esm',
48
50
  // 不写入文件
49
51
  write: false,
50
- plugins,
51
52
  // 忽略所有外部依赖
52
53
  external: ['*'],
53
- ...options
54
+ ...options,
55
+ plugins: [...plugins, ...pl]
54
56
  });
55
57
  if (!result.outputFiles) {
56
58
  return '';
@@ -0,0 +1,26 @@
1
+ import { assetsReg } from '../config.js';
2
+ import { generateModuleContent } from '../utils/content.js';
3
+
4
+ /**
5
+ *
6
+ * @param param0
7
+ */
8
+ const esBuildAsstes = (optoins) => {
9
+ // 默认配置
10
+ const filter = optoins?.filter ?? assetsReg;
11
+ // 返回插件
12
+ return {
13
+ name: 'assets',
14
+ setup(build) {
15
+ build.onLoad({ filter }, args => {
16
+ const content = generateModuleContent(args.path);
17
+ return {
18
+ contents: content,
19
+ loader: 'js'
20
+ };
21
+ });
22
+ }
23
+ };
24
+ };
25
+
26
+ export { esBuildAsstes };
@@ -0,0 +1,73 @@
1
+ import { join, resolve } from 'path';
2
+ import { existsSync } from 'fs';
3
+
4
+ /**
5
+ *
6
+ * @param alias
7
+ * @returns
8
+ */
9
+ const esBuildAlias = (alias) => {
10
+ const entries = alias?.entries;
11
+ return {
12
+ name: 'alias',
13
+ setup(build) {
14
+ // 解析路径时使用 entries
15
+ if (entries) {
16
+ build.onResolve({ filter: /.*/ }, args => {
17
+ const url = args.path;
18
+ for (const { find, replacement } of entries) {
19
+ if (typeof find === 'string' && url.startsWith(find)) {
20
+ const resolvedPath = join(replacement, url.slice(find.length));
21
+ const absolutePath = resolve(resolvedPath);
22
+ if (existsSync(absolutePath)) {
23
+ return {
24
+ path: absolutePath
25
+ };
26
+ }
27
+ const value = checkFileExtensions(absolutePath);
28
+ if (!value)
29
+ return;
30
+ if (value) {
31
+ return {
32
+ path: value
33
+ };
34
+ }
35
+ }
36
+ else if (find instanceof RegExp && find.test(url)) {
37
+ // 正则匹配
38
+ const resolvedPath = url.replace(find, replacement);
39
+ const absolutePath = resolve(resolvedPath);
40
+ if (existsSync(absolutePath)) {
41
+ return {
42
+ path: absolutePath
43
+ };
44
+ }
45
+ const value = checkFileExtensions(absolutePath);
46
+ if (!value)
47
+ return;
48
+ if (value) {
49
+ return {
50
+ path: value
51
+ };
52
+ }
53
+ }
54
+ }
55
+ return null;
56
+ });
57
+ }
58
+ }
59
+ };
60
+ };
61
+ const checkFileExtensions = basePath => {
62
+ const extensions = ['.js', '.ts', '.jsx', '.tsx'];
63
+ for (const ext of extensions) {
64
+ const filePath = `${basePath}${ext}`;
65
+ if (existsSync(filePath)) {
66
+ return filePath;
67
+ }
68
+ }
69
+ // 如果没有找到文件,返回 null
70
+ return null;
71
+ };
72
+
73
+ export { esBuildAlias };
@@ -0,0 +1,6 @@
1
+ type ESBuildCSSOptions = {
2
+ filter?: RegExp
3
+ configPath?: string
4
+ }
5
+
6
+ export type { ESBuildCSSOptions }
@@ -0,0 +1,27 @@
1
+ import { generateCSSModuleContent } from '../utils/content.js';
2
+ import { cssReg } from '../config.js';
3
+
4
+ /**
5
+ * css资源处理插件
6
+ * @param param0
7
+ * @returns
8
+ */
9
+ const esBuildCSS = (optoins) => {
10
+ const filter = optoins?.filter || cssReg;
11
+ // 返回插件
12
+ return {
13
+ name: 'css-loader',
14
+ setup(build) {
15
+ // 加载 CSS/SCSS 文件
16
+ build.onLoad({ filter }, args => {
17
+ const contents = generateCSSModuleContent(args.path);
18
+ return {
19
+ contents: contents,
20
+ loader: 'js'
21
+ };
22
+ });
23
+ }
24
+ };
25
+ };
26
+
27
+ export { esBuildCSS };
@@ -0,0 +1,57 @@
1
+ import { join } from 'path';
2
+ import crypto from 'node:crypto';
3
+
4
+ /**
5
+ * @param inputPath
6
+ * @returns
7
+ */
8
+ const convertPath = (inputPath) => {
9
+ return process.platform === 'win32' ? inputPath.replace(/\\/g, '/') : inputPath;
10
+ };
11
+ /**
12
+ * 生成模块内容
13
+ * @param {string} relativePath 相对路径
14
+ */
15
+ const generateModuleContent = (relativePath) => {
16
+ const contents = [
17
+ 'const createUrl = (basePath, path) => {',
18
+ "const platform = ['linux', 'android', 'darwin'];",
19
+ 'const T = platform.includes(process.platform);',
20
+ 'const reg = T ? /^file:\\/\\// : /^file:\\/\\/\\//;',
21
+ "return new URL(path, basePath).href.replace(reg, '');",
22
+ '};',
23
+ `const fileUrl = createUrl(import.meta.url, '${convertPath(relativePath)}');`,
24
+ 'export default fileUrl;'
25
+ ].join('\n');
26
+ return contents;
27
+ };
28
+ const getRandomName = (str) => {
29
+ // 使用 MD5 算法创建哈希对象
30
+ const hash = crypto.createHash('md5');
31
+ // 更新哈希对象内容
32
+ hash.update(str);
33
+ return hash.digest('hex');
34
+ };
35
+ const chache = {};
36
+ /**
37
+ *
38
+ * @param fileUrl
39
+ * @returns
40
+ */
41
+ const generateCSSModuleContent = (pathURL) => {
42
+ const fileName = getRandomName(pathURL);
43
+ const outputFileURL = convertPath(join(process.cwd(), 'node_modules', 'lvyjs', 'assets', `${fileName}.css`));
44
+ if (!chache[pathURL]) {
45
+ global.lvyWorkerProt.postMessage({
46
+ type: 'CSS_MODULE_GENERATED',
47
+ payload: {
48
+ from: pathURL,
49
+ to: outputFileURL
50
+ }
51
+ });
52
+ chache[pathURL] = true;
53
+ }
54
+ return `export default "${outputFileURL}";`;
55
+ };
56
+
57
+ export { generateCSSModuleContent, generateModuleContent };
package/lib/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export { defineConfig, initConfig, usePlugin } from './loader/store.js';
1
+ export { Options, defineConfig, getOptions, initConfig, usePlugin } from './store.js';
2
+ export { buildAndRun, buildJS } from './rullup/index.js';
3
+ export { ESBuild } from './esbuild/index.js';
package/lib/index.js CHANGED
@@ -1,6 +1,8 @@
1
- import { buildAndRun } from './build/rullup.js';
2
- import { initConfig } from './loader/store.js';
3
- export { defineConfig, usePlugin } from './loader/store.js';
1
+ import { buildAndRun } from './rullup/index.js';
2
+ export { buildJS } from './rullup/index.js';
3
+ import { initConfig } from './store.js';
4
+ export { defineConfig, getOptions, usePlugin } from './store.js';
5
+ export { ESBuild } from './esbuild/index.js';
4
6
 
5
7
  /**
6
8
  * @param input
@@ -39,4 +41,4 @@ const main = async () => {
39
41
  };
40
42
  main();
41
43
 
42
- export { initConfig };
44
+ export { buildAndRun, initConfig };
package/lib/loader.d.ts CHANGED
@@ -1,15 +1,18 @@
1
- type LoaderResult = {
2
- format?: string;
3
- source?: string;
4
- shortCircuit?: boolean;
5
- };
1
+ import { MessagePort } from 'worker_threads';
2
+
3
+ declare global {
4
+ var lvyWorkerProt: MessagePort;
5
+ }
6
+ declare function initialize({ port, lvyConfig }: {
7
+ port: any;
8
+ lvyConfig: any;
9
+ }): Promise<void>;
6
10
  /**
7
- *
8
11
  * @param url
9
12
  * @param context
10
13
  * @param defaultLoad
11
14
  * @returns
12
15
  */
13
- declare const load: (url: string, context: any, defaultLoad: (url: string, context: any) => Promise<LoaderResult>) => Promise<LoaderResult>;
16
+ declare const load: (url: any, context: any, defaultLoad: any) => Promise<any>;
14
17
 
15
- export { load };
18
+ export { initialize, load };
package/lib/loader.js CHANGED
@@ -1,14 +1,14 @@
1
- import { ESBuild } from './loader/esbuild.js';
2
- import { initConfig } from './loader/store.js';
1
+ import { ESBuild } from './esbuild/index.js';
3
2
 
4
- await initConfig();
5
- const platform = ['linux', 'android', 'darwin'];
6
- const T = platform.includes(process.platform);
7
- const reg = T ? /^file:\/\// : /^file:\/\/\//;
3
+ const platform = ['win32'].includes(process.platform);
4
+ const reg = platform ? /^file:\/\/\// : /^file:\/\//;
8
5
  const nodeReg = /(node_modules|node_|node:)/;
9
6
  const jsReg = /\.(js|ts|jsx|tsx)$/;
7
+ async function initialize({ port, lvyConfig }) {
8
+ global.lvyConfig = lvyConfig;
9
+ global.lvyWorkerProt = port;
10
+ }
10
11
  /**
11
- *
12
12
  * @param url
13
13
  * @param context
14
14
  * @param defaultLoad
@@ -28,4 +28,4 @@ const load = async (url, context, defaultLoad) => {
28
28
  });
29
29
  };
30
30
 
31
- export { load };
31
+ export { initialize, load };
package/lib/main.js CHANGED
@@ -1,3 +1,32 @@
1
- import { register } from 'node:module';
1
+ import module from 'node:module';
2
+ import { MessageChannel } from 'node:worker_threads';
3
+ import { postCSS } from './postcss.js';
2
4
 
3
- register('./loader.js', import.meta.url);
5
+ if (!module.register) {
6
+ throw new Error(`This version of Node.js (${process.version}) does not support module.register(). Please upgrade to Node v18.19 or v20.6 and above.`);
7
+ }
8
+ const { port1, port2 } = new MessageChannel();
9
+ const cache = {};
10
+ port1.on('message', msg => {
11
+ if (msg.type == 'CSS_MODULE_GENERATED') {
12
+ const { from, to } = msg.payload;
13
+ if (!cache[from]) {
14
+ postCSS(from, to);
15
+ cache[from] = true;
16
+ }
17
+ }
18
+ else if (msg.type == 'JS_MODULE_GENERATED') ;
19
+ });
20
+ // port1.unref()
21
+ module.register('./loader.js', {
22
+ parentURL: import.meta.url,
23
+ data: {
24
+ port: port2,
25
+ lvyConfig: {
26
+ alias: global.lvyConfig.alias,
27
+ assets: global.lvyConfig.assets,
28
+ styles: global.lvyConfig.styles
29
+ }
30
+ },
31
+ transferList: [port2]
32
+ });
package/lib/postcss.js ADDED
@@ -0,0 +1,104 @@
1
+ import fs from 'fs';
2
+ import postcss from 'postcss';
3
+ import { createRequire } from 'module';
4
+ import { join, resolve, dirname } from 'path';
5
+
6
+ const require = createRequire(import.meta.url);
7
+ const loadPostcssConfig = configPath => {
8
+ const plugins = [];
9
+ let aliasEntries = [];
10
+ if (typeof global.lvyConfig?.alias != 'boolean') {
11
+ aliasEntries = global.lvyConfig.alias?.entries || [];
12
+ }
13
+ if (aliasEntries.length > 0) {
14
+ // 创建 postcss-import 插件并配置别名解析
15
+ try {
16
+ plugins.push(require('postcss-import')({
17
+ resolve: (id, basedir) => {
18
+ // 检查别名
19
+ for (const entry of aliasEntries) {
20
+ if (id.startsWith(entry.find)) {
21
+ const aliasedPath = id.replace(entry.find, entry.replacement);
22
+ return resolve(basedir, aliasedPath); // 返回绝对路径
23
+ }
24
+ }
25
+ return id; // 默认返回原始路径
26
+ }
27
+ }));
28
+ }
29
+ catch (err) {
30
+ console.error(err);
31
+ }
32
+ }
33
+ try {
34
+ if (fs.existsSync(configPath)) {
35
+ const cfg = require(configPath);
36
+ // 添加其他插件
37
+ if (!Array.isArray(cfg.plugins)) {
38
+ const keys = Object.keys(cfg.plugins);
39
+ keys.forEach(key => {
40
+ try {
41
+ const pluginConfig = cfg.plugins[key];
42
+ const plugin = require(key);
43
+ if (typeof plugin === 'function') {
44
+ plugins.push(plugin(pluginConfig));
45
+ }
46
+ else {
47
+ throw new Error(`插件 ${key} 不是有效的 PostCSS 插件函数`);
48
+ }
49
+ }
50
+ catch (err) {
51
+ console.error(`加载 PostCSS 插件 ${key} 失败:`, err);
52
+ }
53
+ });
54
+ }
55
+ else {
56
+ plugins.push(...cfg.plugins);
57
+ }
58
+ return { plugins };
59
+ }
60
+ else {
61
+ throw new Error(`未找到 PostCSS 配置文件: ${configPath}`);
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.error('加载 PostCSS 配置失败:', err);
66
+ return { plugins };
67
+ }
68
+ };
69
+ const postCSS = (inputPath, outputPath) => {
70
+ const configPath = join(process.cwd(), 'postcss.config.cjs');
71
+ const postcssConfig = loadPostcssConfig(configPath);
72
+ const readAndProcessCSS = async () => {
73
+ const css = fs.readFileSync(inputPath, 'utf-8');
74
+ fs.mkdirSync(dirname(outputPath), { recursive: true });
75
+ const result = await postcss(postcssConfig.plugins).process(css, {
76
+ from: inputPath,
77
+ to: outputPath
78
+ });
79
+ fs.writeFileSync(outputPath, result.css);
80
+ if (result.warnings().length) {
81
+ result.warnings().forEach(warn => {
82
+ console.warn(warn.toString());
83
+ });
84
+ }
85
+ const dependencies = result.messages
86
+ .filter(msg => msg.type === 'dependency')
87
+ .map(msg => msg.file);
88
+ for (const dep of dependencies) {
89
+ fs.watch(dep, eventType => {
90
+ if (eventType === 'change') {
91
+ readAndProcessCSS();
92
+ }
93
+ });
94
+ }
95
+ };
96
+ readAndProcessCSS();
97
+ fs.watch(inputPath, eventType => {
98
+ if (eventType === 'change') {
99
+ readAndProcessCSS();
100
+ }
101
+ });
102
+ };
103
+
104
+ export { postCSS };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 打包 JS
3
+ * *** 注意 **
4
+ * 和initConfig配合使用
5
+ * **
6
+ * 确保已经初始化了配置
7
+ * @param inputs
8
+ * @param output
9
+ */
10
+ declare const buildJS: (inputs: string[]) => Promise<void>;
11
+ /**
12
+ *
13
+ * @param script
14
+ */
15
+ declare function buildAndRun(): Promise<void>;
16
+
17
+ export { buildAndRun, buildJS };
@@ -4,10 +4,10 @@ import typescript from '@rollup/plugin-typescript';
4
4
  import commonjs from '@rollup/plugin-commonjs';
5
5
  import json from '@rollup/plugin-json';
6
6
  import styles from 'rollup-plugin-styles';
7
- import { getScriptFiles } from './get-files.js';
7
+ import { getScriptFiles } from './utils/files.js';
8
8
  import alias from '@rollup/plugin-alias';
9
- import { rollupStylesCSSImport } from '../plugins/loader-css.js';
10
- import { rollupAssets } from '../plugins/loader-files.js';
9
+ import { rollupStylesCSSImport } from './plugins/loader-css.js';
10
+ import { rollupAssets } from './plugins/loader-files.js';
11
11
 
12
12
  /**
13
13
  * 用于忽略警告
@@ -35,50 +35,51 @@ const buildJS = async (inputs) => {
35
35
  global.lvyConfig.build = {};
36
36
  // 插件
37
37
  const plugins = [];
38
- if (global.lvyConfig?.alias) {
39
- plugins.push(alias(global.lvyConfig.alias));
38
+ if (typeof global.lvyConfig?.alias !== 'boolean') {
39
+ plugins.push(alias(global.lvyConfig?.alias ?? {}));
40
40
  }
41
- if (global.lvyConfig.assets) {
42
- plugins.push(rollupAssets(global.lvyConfig.assets));
41
+ if (typeof global.lvyConfig?.assets !== 'boolean') {
42
+ plugins.push(rollupAssets(global.lvyConfig?.assets ?? {}));
43
43
  }
44
- else {
45
- plugins.push(rollupAssets());
44
+ if (typeof global.lvyConfig?.styles !== 'boolean') {
45
+ if (!global.lvyConfig.alias)
46
+ global.lvyConfig.alias = {};
47
+ const newAlias = val => {
48
+ const alias = {};
49
+ // 遍历 entries 数组
50
+ val.entries.forEach(entry => {
51
+ alias[entry.find] = entry.replacement;
52
+ });
53
+ return alias;
54
+ };
55
+ plugins.push(styles({
56
+ alias: newAlias(global.lvyConfig?.alias),
57
+ mode: ['inject', () => '']
58
+ }));
59
+ plugins.push(rollupStylesCSSImport(global.lvyConfig.styles));
46
60
  }
61
+ plugins.push(json());
47
62
  if (typeof global.lvyConfig.build != 'boolean') {
48
63
  //
49
64
  for (const key in global.lvyConfig.build) {
50
65
  if (typeof global.lvyConfig.build[key] == 'boolean') {
51
66
  continue;
52
67
  }
53
- if (key === 'styles') {
54
- plugins.push(styles({
55
- mode: ['inject', () => '']
56
- }));
57
- plugins.push(rollupStylesCSSImport(global.lvyConfig.build[key]));
58
- }
59
- else if (key === 'commonjs' && !global.lvyConfig.build['@rollup/plugin-commonjs']) {
68
+ if (key == 'commonjs' && !global.lvyConfig.build['@rollup/plugin-commonjs']) {
60
69
  plugins.push(commonjs(global.lvyConfig.build[key]));
61
70
  }
62
- else if (key === 'json' && !global.lvyConfig.build['@rollup/plugin-json']) {
63
- plugins.push(json(global.lvyConfig.build[key]));
64
- }
65
- else if (key === 'typescript' && !global.lvyConfig.build['@rollup/plugin-typescript']) {
71
+ else if (key == 'typescript' && !global.lvyConfig.build['@rollup/plugin-typescript']) {
66
72
  plugins.push(typescript(global.lvyConfig.build[key]));
67
73
  }
68
- else if (key === 'plugins') {
69
- if (Array.isArray(global.lvyConfig.build[key])) {
70
- for (const plugin of global.lvyConfig.build[key]) {
71
- plugins.push(plugin);
72
- }
73
- }
74
+ else if (key == 'OutputOptions') {
75
+ continue;
74
76
  }
75
- else {
76
- const plugin = (await import(key)).default;
77
- plugins.push(plugin(global.lvyConfig.build[key]));
77
+ else if (key == 'RollupOptions') {
78
+ continue;
78
79
  }
79
80
  }
80
81
  // 如果不存在这些配置
81
- const keys = ['styles', 'commonjs', 'json', 'typescript'];
82
+ const keys = ['commonjs', 'typescript'];
82
83
  for (const key of keys) {
83
84
  // 如果是布尔值
84
85
  if (typeof global.lvyConfig.build[key] == 'boolean') {
@@ -89,31 +90,22 @@ const buildJS = async (inputs) => {
89
90
  continue;
90
91
  }
91
92
  //
92
- if (key == 'styles') {
93
- plugins.push(styles({
94
- mode: ['inject', () => '']
95
- }));
96
- plugins.push(rollupStylesCSSImport());
97
- }
98
- else if (key === 'commonjs') {
93
+ if (key === 'commonjs') {
99
94
  plugins.push(commonjs());
100
95
  }
101
- else if (key === 'json') {
102
- plugins.push(json());
103
- }
104
96
  else if (key === 'typescript') {
105
97
  plugins.push(typescript());
106
98
  }
107
99
  }
108
100
  }
109
- // rollup 配置
110
- const rollupOptions = global.lvyConfig?.rollupOptions ?? {};
111
- const rollupPlugins = global.lvyConfig?.rollupPlugins ?? [];
101
+ const RollupOptions = global.lvyConfig?.build?.RollupOptions ?? {};
102
+ const OutputOptions = global.lvyConfig?.build?.OutputOptions ?? [];
112
103
  // build
113
104
  const bundle = await rollup({
114
105
  input: inputs,
115
- plugins: [...plugins, ...rollupPlugins],
116
- onwarn: onwarn
106
+ plugins: [...plugins],
107
+ onwarn: onwarn,
108
+ ...RollupOptions
117
109
  });
118
110
  // 写入输出文件
119
111
  await bundle.write({
@@ -122,7 +114,7 @@ const buildJS = async (inputs) => {
122
114
  sourcemap: false,
123
115
  preserveModules: true,
124
116
  assetFileNames: 'assets/[name]-[hash][extname]',
125
- ...rollupOptions
117
+ ...OutputOptions
126
118
  });
127
119
  };
128
120
  /**
@@ -130,12 +122,12 @@ const buildJS = async (inputs) => {
130
122
  * @param script
131
123
  */
132
124
  async function buildAndRun() {
125
+ if (!global.lvyConfig)
126
+ global.lvyConfig = {};
127
+ if (!global.lvyConfig.build)
128
+ global.lvyConfig.build = {};
133
129
  // rollup 配置
134
- let inputDir = 'src';
135
- if (global.lvyConfig?.rollupOptions?.input) {
136
- inputDir = global.lvyConfig.rollupOptions.input;
137
- delete global.lvyConfig.rollupOptions['input'];
138
- }
130
+ let inputDir = global.lvyConfig?.build?.OutputOptions?.input ?? 'src';
139
131
  const inputFiles = getScriptFiles(join(process.cwd(), inputDir));
140
132
  await buildJS(inputFiles);
141
133
  }
@@ -1,4 +1,4 @@
1
1
  const assetsReg = /\.(png|jpg|jpeg|gif|svg|webp|ico)$/;
2
- const cssReg = /\.(css|scss)$/;
2
+ const cssReg = /\.(css|scss|less|sass|less)$/;
3
3
 
4
4
  export { assetsReg, cssReg };
@@ -7,7 +7,7 @@ import { cssReg } from './config.js';
7
7
  * @returns
8
8
  */
9
9
  const rollupStylesCSSImport = (options) => {
10
- const { include = cssReg } = options ?? {};
10
+ const include = options?.filter ?? cssReg;
11
11
  const filter = createFilter(include, null);
12
12
  return {
13
13
  name: 'c-css',
@@ -1,13 +1,12 @@
1
- import { Alias } from '@rollup/plugin-alias';
2
- import { RollupStylesCSSImportOptions } from '../plugins/loader-css.js';
3
1
  import { RollupCommonJSOptions } from '@rollup/plugin-commonjs';
4
- import { RollupJsonOptions } from '@rollup/plugin-json';
5
2
  import { RollupTypescriptOptions } from '@rollup/plugin-typescript';
6
3
  import { SameShape, BuildOptions } from 'esbuild';
7
- import { ESBuildCSSOptions } from './plugins.js';
8
- import { RollupBuild } from 'rollup';
4
+ import { RollupOptions, OutputOptions } from 'rollup';
9
5
 
10
- type RollupBuildOptions = Parameters<RollupBuild['write']>['0'];
6
+ interface Alias {
7
+ find: string | RegExp;
8
+ replacement: string;
9
+ }
11
10
  type Options = {
12
11
  /**
13
12
  * 配置调整机及其回调插件
@@ -21,7 +20,7 @@ type Options = {
21
20
  * 别名规则
22
21
  */
23
22
  entries?: Alias[];
24
- };
23
+ } | false;
25
24
  /**
26
25
  * 静态资源识别
27
26
  */
@@ -30,55 +29,47 @@ type Options = {
30
29
  * 过滤得到指定格式的文件识别之为静态资源
31
30
  */
32
31
  filter?: RegExp;
33
- };
34
- /**
35
- *
36
- */
37
- esBuildOptions?: SameShape<BuildOptions, BuildOptions>;
38
- /**
39
- * 运行时配置
40
- */
41
- esbuild?: {
42
- [key: string]: any;
32
+ } | false;
33
+ styles?: {
43
34
  /**
44
- * 样式处理
35
+ * 过滤得到指定格式的文件识别之为静态资源
45
36
  */
46
- styles?: ESBuildCSSOptions | false;
47
- };
37
+ filter?: RegExp;
38
+ } | false;
48
39
  /**
49
- * ⚠️ RollupBuild['write'] 配置
40
+ * 运行时配置
50
41
  */
51
- rollupOptions?: RollupBuildOptions & {
42
+ esbuild?: {
52
43
  /**
53
- * 默认 src
44
+ *
54
45
  */
55
- input?: string;
46
+ options?: SameShape<BuildOptions, BuildOptions>;
56
47
  };
57
- /**
58
- *使用插件
59
- */
60
- rollupPlugins?: any[];
61
48
  /**
62
49
  * 打包时配置
63
50
  */
64
51
  build?: {
65
- [key: string]: any;
66
- /**
67
- * 样式处理配置
68
- */
69
- styles?: RollupStylesCSSImportOptions | false;
70
52
  /**
71
53
  * cjs文件处理
72
54
  */
73
55
  commonjs?: RollupCommonJSOptions | false;
74
- /**
75
- * josn文件处理
76
- */
77
- json?: RollupJsonOptions | false;
78
56
  /**
79
57
  * ts配置
80
58
  */
81
59
  typescript?: RollupTypescriptOptions | false;
60
+ /**
61
+ *
62
+ */
63
+ RollupOptions?: RollupOptions;
64
+ /**
65
+ *
66
+ */
67
+ OutputOptions?: OutputOptions & {
68
+ /**
69
+ * 默认 src
70
+ */
71
+ input?: string;
72
+ };
82
73
  } | false;
83
74
  };
84
75
  /**
@@ -97,10 +88,14 @@ declare global {
97
88
  *
98
89
  */
99
90
  declare const initConfig: () => Promise<void>;
91
+ /**
92
+ * @returns
93
+ */
94
+ declare const getOptions: () => Options;
100
95
  /**
101
96
  * @param param0
102
97
  * @returns
103
98
  */
104
99
  declare const defineConfig: (optoins?: Options) => Options | undefined;
105
100
 
106
- export { type Options, defineConfig, initConfig, usePlugin };
101
+ export { type Options, defineConfig, getOptions, initConfig, usePlugin };
@@ -34,10 +34,14 @@ const initConfig = async () => {
34
34
  }
35
35
  }
36
36
  };
37
+ /**
38
+ * @returns
39
+ */
40
+ const getOptions = () => global.lvyConfig;
37
41
  /**
38
42
  * @param param0
39
43
  * @returns
40
44
  */
41
45
  const defineConfig = (optoins) => optoins;
42
46
 
43
- export { defineConfig, initConfig, usePlugin };
47
+ export { defineConfig, getOptions, initConfig, usePlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lvyjs",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "tsx compile script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
@@ -10,12 +10,10 @@
10
10
  "@rollup/plugin-alias": "^5.1.0",
11
11
  "@rollup/plugin-commonjs": "^28.0.0",
12
12
  "@rollup/plugin-json": "^6.1.0",
13
- "@rollup/plugin-node-resolve": "^15.3.0",
14
13
  "@rollup/plugin-typescript": "^11.1.6",
15
14
  "autoprefixer": "^10.4.20",
16
15
  "cssnano": "^7.0.6",
17
16
  "esbuild": "^0.24.0",
18
- "logger": "^0.0.1",
19
17
  "postcss": "^8.4.47",
20
18
  "postcss-cli": "^11.0.0",
21
19
  "postcss-import": "^16.1.0",
@@ -26,7 +24,6 @@
26
24
  "postcss-styled": "^0.34.0",
27
25
  "postcss-syntax": "^0.36.2",
28
26
  "postcss-url": "^10.1.3",
29
- "json5": "^2.2.3",
30
27
  "rollup": "^4.18.1",
31
28
  "rollup-plugin-dts": "^6.1.1",
32
29
  "rollup-plugin-styles": "^4.0.0",
@@ -69,9 +66,9 @@
69
66
  "registry": "https://registry.npmjs.org",
70
67
  "access": "public"
71
68
  },
72
- "bugs": "https://github.com/lemonade-lab/lvy/issues",
69
+ "bugs": "https://github.com/lvyjs/core/issues",
73
70
  "repository": {
74
71
  "type": "git",
75
- "url": "https://github.com/lemonade-lab/lvy.git"
72
+ "url": "https://github.com/lvyjs/core.git"
76
73
  }
77
74
  }
@@ -1,6 +0,0 @@
1
- type ESBuildCSSOptions = {
2
- filter?: RegExp;
3
- namespace?: string;
4
- };
5
-
6
- export type { ESBuildCSSOptions };
@@ -1,217 +0,0 @@
1
- import { resolve, relative, dirname, join } from 'path';
2
- import { spawn } from 'child_process';
3
- import crypto from 'node:crypto';
4
- import { assetsReg, cssReg } from './config.js';
5
-
6
- /**
7
- *
8
- * @param input
9
- * @param output
10
- */
11
- const startCssPost = (input, output) => {
12
- const run = ['postcss', input, '-o', output, '--watch'];
13
- // 启动 Tailwind 进程
14
- const cssPostProcess = spawn('npx', run, {
15
- stdio: 'inherit',
16
- shell: process.platform === 'win32'
17
- });
18
- cssPostProcess.on('error', err => {
19
- console.error('Failed to start Tailwind process:', err);
20
- });
21
- process.on('exit', () => {
22
- cssPostProcess.kill();
23
- });
24
- };
25
- /**
26
- *
27
- * @param inputPath
28
- * @returns
29
- */
30
- const convertPath = (inputPath) => {
31
- return process.platform === 'win32' ? inputPath.replace(/\\/g, '/') : inputPath;
32
- };
33
- /**
34
- * 生成模块内容
35
- * @param {string} relativePath 相对路径
36
- */
37
- const generateModuleContent = (relativePath) => {
38
- const contents = [
39
- 'const createUrl = (basePath, path) => {',
40
- "const platform = ['linux', 'android', 'darwin'];",
41
- 'const T = platform.includes(process.platform);',
42
- 'const reg = T ? /^file:\\/\\// : /^file:\\/\\/\\//;',
43
- "return new URL(path, basePath).href.replace(reg, '');",
44
- '};',
45
- `const fileUrl = createUrl(import.meta.url, '${convertPath(relativePath)}');`,
46
- 'export default fileUrl;'
47
- ].join('\n');
48
- return contents;
49
- };
50
- const chache = {};
51
- const getHash = (str) => {
52
- // 使用 MD5 算法创建哈希对象
53
- const hash = crypto.createHash('md5');
54
- // 更新哈希对象内容
55
- hash.update(str);
56
- return hash.digest('hex');
57
- };
58
- let entries = null;
59
- const esBuildAlias = (alias) => {
60
- if (!entries) {
61
- entries = alias?.entries ?? [];
62
- }
63
- };
64
- const handleAsstesFile = (url) => {
65
- if (entries) {
66
- for (const { find, replacement } of entries) {
67
- if (typeof find === 'string') {
68
- // 使用 startsWith 处理字符串类型
69
- if (url.startsWith(find)) {
70
- const fileUrl = join(replacement, url.replace(find, ''));
71
- return `export default "${convertPath(fileUrl)}";`;
72
- }
73
- }
74
- else if (find instanceof RegExp) {
75
- // 使用 test 方法处理正则表达式类型
76
- if (find.test(url)) {
77
- const fileUrl = join(replacement, url.replace(find, ''));
78
- return `export default "${convertPath(fileUrl)}";`;
79
- }
80
- }
81
- }
82
- }
83
- return null;
84
- };
85
- /**
86
- *
87
- * @param fileUrl
88
- * @returns
89
- */
90
- const handleCSS = (fileUrl) => {
91
- const hash = getHash(fileUrl);
92
- const outputDir = join(process.cwd(), 'node_modules', 'lvyjs', 'assets', `${hash}.css`);
93
- if (!chache[fileUrl]) {
94
- startCssPost(fileUrl, outputDir);
95
- chache[fileUrl] = true;
96
- }
97
- return outputDir;
98
- };
99
- /**
100
- * 处理路径别名的加载
101
- * @param {string} url URL
102
- * @returns {string|null} 加载结果
103
- */
104
- const handleCSSPath = (url) => {
105
- if (entries) {
106
- for (const { find, replacement } of entries) {
107
- if (typeof find === 'string') {
108
- // 使用 startsWith 处理字符串类型
109
- if (url.startsWith(find)) {
110
- const fileUrl = join(replacement, url.replace(find, ''));
111
- const outputDir = handleCSS(fileUrl);
112
- return `export default "${convertPath(outputDir)}";`;
113
- }
114
- }
115
- else if (find instanceof RegExp) {
116
- // 使用 test 方法处理正则表达式类型
117
- if (find.test(url)) {
118
- const fileUrl = join(replacement, url.replace(find, ''));
119
- const outputDir = handleCSS(fileUrl);
120
- return `export default "${convertPath(outputDir)}";`;
121
- }
122
- }
123
- }
124
- }
125
- return null;
126
- };
127
- /**
128
- *
129
- * @param param0
130
- */
131
- const esBuildAsstes = (optoins) => {
132
- // 默认配置
133
- const filter = optoins?.filter ?? assetsReg;
134
- const namespace = 'assets';
135
- // 返回插件
136
- return {
137
- name: 'assets-loader',
138
- setup(build) {
139
- const outputDirs = new Map();
140
- // 过滤图片文件
141
- build.onResolve({ filter }, args => {
142
- const dir = resolve(args.resolveDir, args.path);
143
- outputDirs.set(dir, args.importer);
144
- return {
145
- path: dir,
146
- namespace
147
- };
148
- });
149
- build.onLoad({ filter, namespace }, async (args) => {
150
- if (!outputDirs.has(args.path))
151
- return null;
152
- const outputDir = outputDirs.get(args.path);
153
- const relativePath = relative(dirname(outputDir), args.path);
154
- // 不管是别名资源。都只是需要返回一个路径
155
- const aliasResult = handleAsstesFile(relativePath);
156
- if (aliasResult) {
157
- return {
158
- contents: aliasResult,
159
- loader: 'js'
160
- };
161
- }
162
- return {
163
- contents: generateModuleContent(relativePath),
164
- loader: 'js'
165
- };
166
- });
167
- }
168
- };
169
- };
170
- /**
171
- * css资源处理插件
172
- * @param param0
173
- * @returns
174
- */
175
- const esBuildCSS = (optoins) => {
176
- const filter = optoins?.filter || cssReg;
177
- const namespace = optoins?.namespace || 'css';
178
- // 返回插件
179
- return {
180
- name: 'css-loader',
181
- setup(build) {
182
- const outputDirs = new Map();
183
- // 过滤 CSS/SCSS 文件
184
- build.onResolve({ filter }, args => {
185
- const dir = resolve(args.resolveDir, args.path);
186
- outputDirs.set(dir, args.importer);
187
- return {
188
- path: dir,
189
- namespace
190
- };
191
- });
192
- // 加载 CSS/SCSS 文件
193
- build.onLoad({ filter, namespace }, async (args) => {
194
- if (!outputDirs.has(args.path))
195
- return null;
196
- const outputDir = outputDirs.get(args.path);
197
- // 计算相对路径
198
- const relativePath = relative(dirname(outputDir), args.path);
199
- // 处理路径别名的加载
200
- const aliasResult = handleCSSPath(relativePath);
201
- if (aliasResult) {
202
- return {
203
- contents: aliasResult,
204
- loader: 'js'
205
- };
206
- }
207
- // 不是别名资源
208
- return {
209
- contents: `export default "${convertPath(handleCSS(args.path))}";`,
210
- loader: 'js'
211
- };
212
- });
213
- }
214
- };
215
- };
216
-
217
- export { esBuildAlias, esBuildAsstes, esBuildCSS };
package/lib/main.d.ts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }
@@ -1,2 +0,0 @@
1
- export { RollupStylesCSSImportOptions, rollupStylesCSSImport } from './loader-css.js';
2
- export { RollupAssetsOptions, rollupAssets } from './loader-files.js';
@@ -1,2 +0,0 @@
1
- export { rollupStylesCSSImport } from './loader-css.js';
2
- export { rollupAssets } from './loader-files.js';
@@ -1,5 +0,0 @@
1
- type RollupStylesCSSImportOptions = {
2
- include?: RegExp;
3
- };
4
-
5
- export type { RollupStylesCSSImportOptions };
@@ -1,12 +0,0 @@
1
- import { InputPluginOption } from 'rollup';
2
-
3
- type RollupAssetsOptions = {
4
- filter?: RegExp;
5
- };
6
- /**
7
- * @param {Object} options
8
- * @returns {Object}
9
- */
10
- declare const rollupAssets: (options?: RollupAssetsOptions) => InputPluginOption;
11
-
12
- export { type RollupAssetsOptions, rollupAssets };
File without changes