lvyjs 0.2.20 → 0.2.22

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/bin/index.js CHANGED
@@ -9,13 +9,23 @@ const currentFilePath = fileURLToPath(import.meta.url)
9
9
  const currentDirPath = dirname(currentFilePath)
10
10
  const pkgFilr = join(currentDirPath, '../package.json')
11
11
  const jsFile = join(currentDirPath, '../lib/index.js')
12
+ const loaderFile = join(currentDirPath, '../lib/main.js')
12
13
  const jsdir = relative(process.cwd(), jsFile)
13
14
  const require = createRequire(import.meta.url)
14
- const tsxDir = require.resolve('tsx/cli')
15
+ // const tsxDir = require.resolve('tsx/cli')
16
+ // 构建时,使用 rollup
15
17
  if (args.includes('build')) {
16
18
  const argsx = args.filter(arg => arg !== 'build')
17
- const msg = fork(tsxDir, [jsdir, '--lvy-build', ...argsx], {
19
+ const msg = fork(jsdir, ['--lvy-build', ...argsx], {
18
20
  stdio: 'inherit',
21
+ // 自己挂 execArgv
22
+ execArgv: [
23
+ ...process.execArgv,
24
+ '--require',
25
+ require.resolve('tsx/preflight'),
26
+ '--import',
27
+ require.resolve('tsx')
28
+ ],
19
29
  env: Object.assign({}, process.env, {
20
30
  PKG_DIR: pkgFilr
21
31
  }),
@@ -25,6 +35,7 @@ if (args.includes('build')) {
25
35
  console.error(msg.error)
26
36
  process.exit()
27
37
  }
38
+ // 运行时,使用 tsx
28
39
  } else if (args.includes('dev')) {
29
40
  const argsx = args.filter(arg => arg !== 'dev')
30
41
  const argv = [jsdir, '--lvy-dev']
@@ -32,8 +43,18 @@ if (args.includes('build')) {
32
43
  argv.unshift('--clear-screen=false')
33
44
  argv.unshift('watch')
34
45
  }
35
- const msg = fork(tsxDir, [...argv, ...argsx], {
46
+ const msg = fork(jsdir, [...argv, ...argsx], {
36
47
  stdio: 'inherit',
48
+ // 自己挂 execArgv
49
+ execArgv: [
50
+ ...process.execArgv,
51
+ '--require',
52
+ require.resolve('tsx/preflight'),
53
+ '--import',
54
+ require.resolve('tsx'),
55
+ '--import',
56
+ loaderFile
57
+ ],
37
58
  env: Object.assign({}, process.env, {
38
59
  PKG_DIR: pkgFilr
39
60
  }),
package/lib/config.js CHANGED
@@ -7,6 +7,9 @@ const stylesRegExp = /\.(css|scss|less|sass|less)$/;
7
7
  */
8
8
  const createAlias = val => {
9
9
  const alias = {};
10
+ if (!Array.isArray(val.entries)) {
11
+ return alias;
12
+ }
10
13
  // 遍历 entries 数组
11
14
  val.entries.forEach(entry => {
12
15
  alias[entry.find] = entry.replacement;
package/lib/loader.js CHANGED
@@ -24,7 +24,7 @@ async function resolve(specifier, context, nextResolve) {
24
24
  if (!global.lvyConfig?.alias) {
25
25
  global.lvyConfig.alias = {};
26
26
  }
27
- if (global.lvyConfig.alias?.entries) {
27
+ if (Array.isArray(global.lvyConfig.alias?.entries)) {
28
28
  for (const { find, replacement } of global.lvyConfig.alias?.entries) {
29
29
  if (specifier.startsWith(find)) {
30
30
  const parentURL = `${baseURL}${convertPath(specifier.replace(find, replacement))}`;
@@ -0,0 +1,26 @@
1
+ import crypto from 'node:crypto';
2
+ import { convertPath } from '../config.js';
3
+
4
+ /**
5
+ * 生成静态资源模块内容
6
+ * @param relativePath 相对路径
7
+ */
8
+ const generateModuleContent = (relativePath) => {
9
+ const baseURL = decodeURIComponent(relativePath);
10
+ const contents = [
11
+ `const reg = ['win32'].includes(process.platform) ? /^file:\\/\\/\\// : /^file:\\/\\// ;`,
12
+ `const fileUrl = import.meta.resolve('${convertPath(baseURL)}').replace(reg, '');`,
13
+ 'export default fileUrl;'
14
+ ].join('\n');
15
+ return contents;
16
+ };
17
+ /**
18
+ * 生成随机文件名
19
+ */
20
+ const getRandomName = (str) => {
21
+ const hash = crypto.createHash('md5');
22
+ hash.update(str);
23
+ return hash.digest('hex');
24
+ };
25
+
26
+ export { generateModuleContent, getRandomName };
@@ -0,0 +1,202 @@
1
+ import fs from 'fs';
2
+ import postcss from 'postcss';
3
+ import { createRequire } from 'module';
4
+ import { join, resolve, dirname, isAbsolute } from 'path';
5
+ import { convertPath, createAlias } from '../config.js';
6
+
7
+ const require = createRequire(import.meta.url);
8
+ const config = {
9
+ css: null,
10
+ sass: null,
11
+ less: null,
12
+ scss: null
13
+ };
14
+ function LessAliasPlugin(aliases) {
15
+ return {
16
+ install: function (less, pluginManager) {
17
+ const AliasFileManager = new less.FileManager();
18
+ AliasFileManager.loadFile = function (filename, currentDirectory, options, environment) {
19
+ // 替换路径中的别名
20
+ for (const alias in aliases) {
21
+ if (filename.startsWith(alias)) {
22
+ filename = filename.replace(alias, aliases[alias]);
23
+ break;
24
+ }
25
+ }
26
+ const fullPath = isAbsolute(filename) ? filename : resolve(currentDirectory, filename);
27
+ return less.FileManager.prototype.loadFile.call(this, fullPath, currentDirectory, options, environment);
28
+ };
29
+ // 注册自定义文件管理器
30
+ pluginManager.addFileManager(AliasFileManager);
31
+ },
32
+ minVersion: [3, 0] // 支持的最低 LESS 版本
33
+ };
34
+ }
35
+ /**
36
+ *
37
+ * @param configPath
38
+ * @param typing
39
+ * @returns
40
+ */
41
+ const loadPostcssConfig = (configPath, typing) => {
42
+ if (config[typing]) {
43
+ return {
44
+ plugins: config[typing]
45
+ };
46
+ }
47
+ const plugins = [];
48
+ let aliasEntries = [];
49
+ if (typeof global.lvyConfig?.alias != 'boolean') {
50
+ aliasEntries = global.lvyConfig.alias?.entries || [];
51
+ }
52
+ const includeKeys = ['postcss-import', 'postcss-url', 'autoprefixer'];
53
+ //
54
+ if (aliasEntries.length > 0) {
55
+ // 创建 postcss-import 插件并配置别名解析
56
+ try {
57
+ plugins.push(require('postcss-import')({
58
+ resolve: (id, basedir) => {
59
+ // 检查别名
60
+ for (const entry of aliasEntries) {
61
+ if (id.startsWith(entry.find)) {
62
+ const aliasedPath = id.replace(entry.find, entry.replacement);
63
+ return convertPath(resolve(basedir, aliasedPath));
64
+ }
65
+ }
66
+ return id; // 默认返回原始路径
67
+ }
68
+ }));
69
+ }
70
+ catch (err) {
71
+ console.error(err);
72
+ }
73
+ try {
74
+ plugins.push(require('postcss-url')({
75
+ url: asset => {
76
+ // 使用 resolve 逻辑处理 URL
77
+ for (const entry of aliasEntries) {
78
+ if (asset.url.startsWith(entry.find)) {
79
+ const aliasedPath = asset.url.replace(entry.find, entry.replacement);
80
+ return convertPath(aliasedPath);
81
+ }
82
+ }
83
+ return convertPath(asset.url);
84
+ }
85
+ }));
86
+ }
87
+ catch (err) {
88
+ console.error(err);
89
+ }
90
+ }
91
+ for (let i = 2; i < includeKeys.length; i++) {
92
+ plugins.push(require(includeKeys[i])({}));
93
+ }
94
+ try {
95
+ if (fs.existsSync(configPath)) {
96
+ const cfg = require(configPath);
97
+ // 添加其他插件
98
+ if (!Array.isArray(cfg.plugins)) {
99
+ const keys = Object.keys(cfg.plugins);
100
+ for (const key of keys) {
101
+ try {
102
+ if (includeKeys.includes(key))
103
+ continue;
104
+ const pluginConfig = cfg.plugins[key];
105
+ const plugin = require(key);
106
+ if (typeof plugin === 'function') {
107
+ plugins.push(plugin(pluginConfig));
108
+ }
109
+ else {
110
+ throw new Error(`插件 ${key} 不是有效的 PostCSS 插件函数`);
111
+ }
112
+ }
113
+ catch (err) {
114
+ console.error(`加载 PostCSS 插件 ${key} 失败:`, err);
115
+ }
116
+ }
117
+ }
118
+ else {
119
+ plugins.push(...cfg.plugins);
120
+ }
121
+ }
122
+ }
123
+ catch (err) {
124
+ console.error('加载 PostCSS 配置失败:', err);
125
+ }
126
+ config[typing] = plugins;
127
+ return {
128
+ plugins: config[typing]
129
+ };
130
+ };
131
+ /**
132
+ *
133
+ * @param inputPath
134
+ * @param outputPath
135
+ * @returns
136
+ */
137
+ const postCSS = (inputPath, outputPath) => {
138
+ const configPath = join(process.cwd(), 'postcss.config.cjs');
139
+ let typing = 'css';
140
+ let parser = undefined;
141
+ if (/\.sass$/.test(inputPath)) {
142
+ typing = 'sass';
143
+ }
144
+ else if (/\.less$/.test(inputPath)) {
145
+ typing = 'less';
146
+ }
147
+ else if (/\.scss$/.test(inputPath)) {
148
+ typing = 'scss';
149
+ }
150
+ const postcssConfig = loadPostcssConfig(configPath, 'css');
151
+ if (!postcssConfig)
152
+ return;
153
+ const readAndProcessCSS = async () => {
154
+ let css = '';
155
+ if (typing === 'less') {
156
+ const less = require('less');
157
+ const lessResult = await less.render(fs.readFileSync(inputPath, 'utf-8'), {
158
+ filename: inputPath,
159
+ plugins: [LessAliasPlugin(createAlias(global.lvyConfig?.alias))] // 使用插件
160
+ });
161
+ css = lessResult.css;
162
+ }
163
+ else if (typing === 'sass' || typing === 'scss') {
164
+ const sass = require('sass');
165
+ const sassResult = sass.renderSync({ file: inputPath });
166
+ css = sassResult.css.toString();
167
+ }
168
+ else {
169
+ css = fs.readFileSync(inputPath, 'utf-8');
170
+ }
171
+ fs.mkdirSync(dirname(outputPath), { recursive: true });
172
+ const result = await postcss(postcssConfig.plugins).process(css, {
173
+ parser: parser,
174
+ from: inputPath,
175
+ to: outputPath
176
+ });
177
+ fs.writeFileSync(outputPath, result.css);
178
+ if (result.warnings().length) {
179
+ result.warnings().forEach(warn => {
180
+ console.warn(warn.toString());
181
+ });
182
+ }
183
+ const dependencies = result.messages
184
+ .filter(msg => msg.type === 'dependency')
185
+ .map(msg => msg.file);
186
+ for (const dep of dependencies) {
187
+ fs.watch(dep, eventType => {
188
+ if (eventType === 'change') {
189
+ readAndProcessCSS();
190
+ }
191
+ });
192
+ }
193
+ };
194
+ readAndProcessCSS();
195
+ fs.watch(inputPath, eventType => {
196
+ if (eventType === 'change') {
197
+ readAndProcessCSS();
198
+ }
199
+ });
200
+ };
201
+
202
+ export { LessAliasPlugin as default, postCSS };
@@ -54,6 +54,9 @@ const buildJS = async (inputs) => {
54
54
  plugins.push(rollupStylesCSSImport(global.lvyConfig.styles));
55
55
  }
56
56
  plugins.push(json());
57
+ const OutputOptions = global.lvyConfig?.build?.OutputOptions ?? [];
58
+ // 获取 dir 的值
59
+ const outputDir = OutputOptions['dir'] || 'lib';
57
60
  if (typeof global.lvyConfig.build != 'boolean') {
58
61
  //
59
62
  for (const key in global.lvyConfig.build) {
@@ -64,7 +67,11 @@ const buildJS = async (inputs) => {
64
67
  plugins.push(commonjs(global.lvyConfig.build[key]));
65
68
  }
66
69
  else if (key == 'typescript' && !global.lvyConfig.build['@rollup/plugin-typescript']) {
67
- plugins.push(typescript(global.lvyConfig.build[key]));
70
+ const config = global.lvyConfig.build[key] || {};
71
+ if (config.declarationDir === undefined) {
72
+ config.declarationDir = outputDir;
73
+ }
74
+ plugins.push(typescript(config));
68
75
  }
69
76
  else if (key == 'OutputOptions') {
70
77
  continue;
@@ -103,9 +110,6 @@ const buildJS = async (inputs) => {
103
110
  ...RollupOptions,
104
111
  plugins: Array.isArray(pl) ? [...plugins, ...pl] : pl
105
112
  });
106
- const OutputOptions = global.lvyConfig?.build?.OutputOptions ?? [];
107
- // 获取 dir 的值
108
- const outputDir = OutputOptions['dir'] || 'lib';
109
113
  // 写入输出文件
110
114
  const { output } = await bundle.write({
111
115
  dir: outputDir,
package/lib/start.js CHANGED
@@ -15,9 +15,6 @@ const onDev = async () => {
15
15
  await apps.push(plugin(global.lvyConfig));
16
16
  }
17
17
  }
18
- // 执行loader
19
- await import('./main.js');
20
- //
21
18
  for (const app of apps) {
22
19
  if (!app) {
23
20
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lvyjs",
3
- "version": "0.2.20",
3
+ "version": "0.2.22",
4
4
  "description": "tsx compile script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
@@ -29,26 +29,31 @@
29
29
  "exports": {
30
30
  ".": {
31
31
  "import": "./lib/index.js",
32
- "types": "./lib/index.d.ts"
32
+ "types": "./lib/index.d.ts",
33
+ "require": "./lib/index.js"
33
34
  },
34
35
  "./loader": {
35
36
  "import": "./lib/loader.js",
36
- "types": "./lib/loader.d.ts"
37
+ "types": "./lib/loader.d.ts",
38
+ "require": "./lib/loader.js"
37
39
  },
38
40
  "./register": {
39
41
  "import": "./lib/main.js",
40
- "types": "./lib/main.d.ts"
42
+ "types": "./lib/main.d.ts",
43
+ "require": "./lib/main.js"
41
44
  },
42
45
  "./env": {
43
46
  "types": "./env.d.ts"
44
47
  },
45
48
  "./tsconfig.json": {
46
49
  "import": "./tsconfig.json",
47
- "types": "./tsconfig.json"
50
+ "types": "./tsconfig.json",
51
+ "require": "./tsconfig.json"
48
52
  },
49
53
  "./tsconfig": {
50
54
  "import": "./tsconfig.json",
51
- "types": "./tsconfig.json"
55
+ "types": "./tsconfig.json",
56
+ "require": "./tsconfig.json"
52
57
  }
53
58
  },
54
59
  "bin": {