lvyjs 0.2.1 → 0.2.2
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 +1 -1
- package/bin/index.js +14 -19
- package/lib/esbuild/config.js +4 -0
- package/lib/esbuild/index.d.ts +8 -0
- package/lib/esbuild/index.js +62 -0
- package/lib/esbuild/plugins/Asstes.js +26 -0
- package/lib/esbuild/plugins/alias.js +41 -0
- package/lib/esbuild/plugins/css.d.ts +6 -0
- package/lib/esbuild/plugins/css.js +27 -0
- package/lib/esbuild/utils/content.js +59 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.js +33 -33
- package/lib/loader.d.ts +8 -8
- package/lib/loader.js +22 -22
- package/lib/main.js +32 -2
- package/lib/postcss.js +100 -0
- package/lib/rullup/index.d.ts +17 -0
- package/lib/rullup/index.js +127 -0
- package/lib/rullup/plugins/config.js +4 -0
- package/lib/rullup/plugins/loader-css.js +58 -0
- package/lib/rullup/plugins/loader-files.js +40 -0
- package/lib/rullup/utils/files.js +27 -0
- package/lib/store.d.ts +111 -0
- package/lib/store.js +46 -0
- package/package.json +3 -5
- package/lib/build/get-files.js +0 -26
- package/lib/build/rullup.js +0 -143
- package/lib/loader/config.js +0 -4
- package/lib/loader/esbuild.js +0 -62
- package/lib/loader/plugins.d.ts +0 -6
- package/lib/loader/plugins.js +0 -217
- package/lib/loader/store.d.ts +0 -106
- package/lib/loader/store.js +0 -43
- package/lib/main.d.ts +0 -2
- package/lib/plugins/config.js +0 -4
- package/lib/plugins/index.d.ts +0 -2
- package/lib/plugins/index.js +0 -2
- package/lib/plugins/loader-css.d.ts +0 -5
- package/lib/plugins/loader-css.js +0 -60
- package/lib/plugins/loader-files.d.ts +0 -12
- package/lib/plugins/loader-files.js +0 -40
package/README.md
CHANGED
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
|
-
|
|
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, {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import esbuild from 'esbuild'
|
|
2
|
+
import { esBuildCSS } from './plugins/css.js'
|
|
3
|
+
import { esBuildAlias } from './plugins/alias.js'
|
|
4
|
+
import { esBuildAsstes } from './plugins/Asstes.js'
|
|
5
|
+
|
|
6
|
+
// 插件
|
|
7
|
+
const plugins = []
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
const initPlugins = () => {
|
|
12
|
+
if (typeof global.lvyConfig?.alias != 'boolean') {
|
|
13
|
+
plugins.push(esBuildAlias(global.lvyConfig.alias))
|
|
14
|
+
}
|
|
15
|
+
if (typeof global.lvyConfig?.assets != 'boolean') {
|
|
16
|
+
plugins.push(esBuildAsstes(global.lvyConfig.assets))
|
|
17
|
+
}
|
|
18
|
+
if (typeof global.lvyConfig?.styles != 'boolean') {
|
|
19
|
+
plugins.push(esBuildCSS(global.lvyConfig?.styles ?? {}))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param input
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
const ESBuild = async input => {
|
|
28
|
+
// 如果没有配置
|
|
29
|
+
if (!global.lvyConfig) global.lvyConfig = {}
|
|
30
|
+
if (!global.lvyConfig.esbuild) global.lvyConfig.esbuild = {}
|
|
31
|
+
// 没有插件时,检查是否有可用插件。
|
|
32
|
+
if (plugins.length === 0) {
|
|
33
|
+
// init plugisn
|
|
34
|
+
await initPlugins()
|
|
35
|
+
}
|
|
36
|
+
const options = global.lvyConfig?.esbuild?.options ?? {}
|
|
37
|
+
const pl = options?.plugins ?? []
|
|
38
|
+
// 构建
|
|
39
|
+
const result = await esbuild.build({
|
|
40
|
+
// 入口文件
|
|
41
|
+
entryPoints: [input],
|
|
42
|
+
//
|
|
43
|
+
bundle: true,
|
|
44
|
+
// 平台
|
|
45
|
+
platform: 'node',
|
|
46
|
+
// 输出格式
|
|
47
|
+
format: 'esm',
|
|
48
|
+
// 不写入文件
|
|
49
|
+
write: false,
|
|
50
|
+
// 忽略所有外部依赖
|
|
51
|
+
external: ['*'],
|
|
52
|
+
...options,
|
|
53
|
+
plugins: [...plugins, ...pl]
|
|
54
|
+
})
|
|
55
|
+
if (!result.outputFiles) {
|
|
56
|
+
return ''
|
|
57
|
+
}
|
|
58
|
+
// 返回结果
|
|
59
|
+
return result.outputFiles.map(file => new TextDecoder().decode(file.contents)).join('\n')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { ESBuild }
|
|
@@ -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,41 @@
|
|
|
1
|
+
import { join, resolve } from 'path'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param alias
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
const esBuildAlias = alias => {
|
|
9
|
+
const entries = alias?.entries
|
|
10
|
+
return {
|
|
11
|
+
name: 'alias',
|
|
12
|
+
setup(build) {
|
|
13
|
+
// 解析路径时使用 entries
|
|
14
|
+
if (entries) {
|
|
15
|
+
build.onResolve({ filter: /.*/ }, args => {
|
|
16
|
+
const url = args.path
|
|
17
|
+
for (const { find, replacement } of entries) {
|
|
18
|
+
if (typeof find === 'string' && url.startsWith(find)) {
|
|
19
|
+
// 字符串匹配
|
|
20
|
+
const resolvedPath = join(replacement, url.slice(find.length))
|
|
21
|
+
const absolutePath = resolve(resolvedPath)
|
|
22
|
+
return {
|
|
23
|
+
path: absolutePath
|
|
24
|
+
}
|
|
25
|
+
} else if (find instanceof RegExp && find.test(url)) {
|
|
26
|
+
// 正则匹配
|
|
27
|
+
const resolvedPath = url.replace(find, replacement)
|
|
28
|
+
const absolutePath = resolve(resolvedPath)
|
|
29
|
+
return {
|
|
30
|
+
path: absolutePath
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { esBuildAlias }
|
|
@@ -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,59 @@
|
|
|
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(
|
|
44
|
+
join(process.cwd(), 'node_modules', 'lvyjs', 'assets', `${fileName}.css`)
|
|
45
|
+
)
|
|
46
|
+
if (!chache[pathURL]) {
|
|
47
|
+
global.lvyWorkerProt.postMessage({
|
|
48
|
+
type: 'CSS_MODULE_GENERATED',
|
|
49
|
+
payload: {
|
|
50
|
+
from: pathURL,
|
|
51
|
+
to: outputFileURL
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
chache[pathURL] = true
|
|
55
|
+
}
|
|
56
|
+
return `export default "${outputFileURL}";`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { generateCSSModuleContent, generateModuleContent }
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import { buildAndRun } from './
|
|
2
|
-
|
|
3
|
-
|
|
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
|
|
7
9
|
*/
|
|
8
10
|
const onDev = async () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
11
|
+
const apps = []
|
|
12
|
+
if (Array.isArray(global.lvyConfig?.plugins)) {
|
|
13
|
+
// 修改config
|
|
14
|
+
for (const plugin of global.lvyConfig.plugins) {
|
|
15
|
+
if (!plugin) {
|
|
16
|
+
continue
|
|
17
|
+
}
|
|
18
|
+
apps.push(plugin(global.lvyConfig))
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (typeof app == 'function')
|
|
27
|
-
app(global.lvyConfig);
|
|
20
|
+
}
|
|
21
|
+
// 执行loader
|
|
22
|
+
await import('./main.js')
|
|
23
|
+
//
|
|
24
|
+
for (const app of apps) {
|
|
25
|
+
if (!app) {
|
|
26
|
+
continue
|
|
28
27
|
}
|
|
29
|
-
|
|
28
|
+
if (typeof app == 'function') app(global.lvyConfig)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
30
31
|
const main = async () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
main();
|
|
32
|
+
if (process.argv.includes('--lvy-dev')) {
|
|
33
|
+
await initConfig()
|
|
34
|
+
onDev()
|
|
35
|
+
} else if (process.argv.includes('--lvy-build')) {
|
|
36
|
+
await initConfig()
|
|
37
|
+
buildAndRun()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
main()
|
|
41
41
|
|
|
42
|
-
export { initConfig }
|
|
42
|
+
export { buildAndRun, initConfig }
|
package/lib/loader.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
1
|
+
import { MessagePort } from 'worker_threads'
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
var lvyWorkerProt: MessagePort
|
|
5
|
+
}
|
|
6
|
+
declare function initialize({ port, lvyConfig }: { port: any; lvyConfig: any }): Promise<void>
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
8
|
* @param url
|
|
9
9
|
* @param context
|
|
10
10
|
* @param defaultLoad
|
|
11
11
|
* @returns
|
|
12
12
|
*/
|
|
13
|
-
declare const load: (url:
|
|
13
|
+
declare const load: (url: any, context: any, defaultLoad: any) => Promise<any>
|
|
14
14
|
|
|
15
|
-
export { load }
|
|
15
|
+
export { initialize, load }
|
package/lib/loader.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { ESBuild } from './
|
|
2
|
-
import { initConfig } from './loader/store.js';
|
|
1
|
+
import { ESBuild } from './esbuild/index.js'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
const platform = ['win32'].includes(process.platform)
|
|
4
|
+
const reg = platform ? /^file:\/\/\// : /^file:\/\//
|
|
5
|
+
const nodeReg = /(node_modules|node_|node:)/
|
|
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
|
|
15
15
|
* @returns
|
|
16
16
|
*/
|
|
17
17
|
const load = async (url, context, defaultLoad) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
18
|
+
if (nodeReg.test(url)) {
|
|
19
|
+
return defaultLoad(url, context)
|
|
20
|
+
}
|
|
21
|
+
if (!jsReg.test(url)) {
|
|
22
|
+
return defaultLoad(url, context)
|
|
23
|
+
}
|
|
24
|
+
const code = await ESBuild(url.replace(reg, ''))
|
|
25
|
+
return defaultLoad(url, {
|
|
26
|
+
format: 'module',
|
|
27
|
+
source: code
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
30
|
|
|
31
|
-
export { load }
|
|
31
|
+
export { initialize, load }
|
package/lib/main.js
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
-
import
|
|
1
|
+
import module from 'node:module'
|
|
2
|
+
import { MessageChannel } from 'node:worker_threads'
|
|
3
|
+
import { postCSS } from './postcss.js'
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
if (!module.register) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
`This version of Node.js (${process.version}) does not support module.register(). Please upgrade to Node v18.19 or v20.6 and above.`
|
|
8
|
+
)
|
|
9
|
+
}
|
|
10
|
+
const { port1, port2 } = new MessageChannel()
|
|
11
|
+
const cache = {}
|
|
12
|
+
port1.on('message', msg => {
|
|
13
|
+
if (msg.type == 'CSS_MODULE_GENERATED') {
|
|
14
|
+
const { from, to } = msg.payload
|
|
15
|
+
if (!cache[from]) {
|
|
16
|
+
postCSS(from, to)
|
|
17
|
+
cache[from] = true
|
|
18
|
+
}
|
|
19
|
+
} else if (msg.type == 'JS_MODULE_GENERATED');
|
|
20
|
+
})
|
|
21
|
+
// port1.unref()
|
|
22
|
+
module.register('./loader.js', {
|
|
23
|
+
parentURL: import.meta.url,
|
|
24
|
+
data: {
|
|
25
|
+
port: port2,
|
|
26
|
+
lvyConfig: {
|
|
27
|
+
alias: global.lvyConfig.alias,
|
|
28
|
+
assets: global.lvyConfig.assets,
|
|
29
|
+
styles: global.lvyConfig.styles
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
transferList: [port2]
|
|
33
|
+
})
|
package/lib/postcss.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
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(
|
|
17
|
+
require('postcss-import')({
|
|
18
|
+
resolve: (id, basedir) => {
|
|
19
|
+
// 检查别名
|
|
20
|
+
for (const entry of aliasEntries) {
|
|
21
|
+
if (id.startsWith(entry.find)) {
|
|
22
|
+
const aliasedPath = id.replace(entry.find, entry.replacement)
|
|
23
|
+
return resolve(basedir, aliasedPath) // 返回绝对路径
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return id // 默认返回原始路径
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
)
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error(err)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
if (fs.existsSync(configPath)) {
|
|
36
|
+
const cfg = require(configPath)
|
|
37
|
+
// 添加其他插件
|
|
38
|
+
if (!Array.isArray(cfg.plugins)) {
|
|
39
|
+
const keys = Object.keys(cfg.plugins)
|
|
40
|
+
keys.forEach(key => {
|
|
41
|
+
try {
|
|
42
|
+
const pluginConfig = cfg.plugins[key]
|
|
43
|
+
const plugin = require(key)
|
|
44
|
+
if (typeof plugin === 'function') {
|
|
45
|
+
plugins.push(plugin(pluginConfig))
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error(`插件 ${key} 不是有效的 PostCSS 插件函数`)
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error(`加载 PostCSS 插件 ${key} 失败:`, err)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
} else {
|
|
54
|
+
plugins.push(...cfg.plugins)
|
|
55
|
+
}
|
|
56
|
+
return { plugins }
|
|
57
|
+
} else {
|
|
58
|
+
throw new Error(`未找到 PostCSS 配置文件: ${configPath}`)
|
|
59
|
+
}
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error('加载 PostCSS 配置失败:', err)
|
|
62
|
+
return { plugins }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const postCSS = (inputPath, outputPath) => {
|
|
66
|
+
const configPath = join(process.cwd(), 'postcss.config.cjs')
|
|
67
|
+
const postcssConfig = loadPostcssConfig(configPath)
|
|
68
|
+
const readAndProcessCSS = async () => {
|
|
69
|
+
const css = fs.readFileSync(inputPath, 'utf-8')
|
|
70
|
+
fs.mkdirSync(dirname(outputPath), { recursive: true })
|
|
71
|
+
const result = await postcss(postcssConfig.plugins).process(css, {
|
|
72
|
+
from: inputPath,
|
|
73
|
+
to: outputPath
|
|
74
|
+
})
|
|
75
|
+
fs.writeFileSync(outputPath, result.css)
|
|
76
|
+
if (result.warnings().length) {
|
|
77
|
+
result.warnings().forEach(warn => {
|
|
78
|
+
console.warn(warn.toString())
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
const dependencies = result.messages
|
|
82
|
+
.filter(msg => msg.type === 'dependency')
|
|
83
|
+
.map(msg => msg.file)
|
|
84
|
+
for (const dep of dependencies) {
|
|
85
|
+
fs.watch(dep, eventType => {
|
|
86
|
+
if (eventType === 'change') {
|
|
87
|
+
readAndProcessCSS()
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
readAndProcessCSS()
|
|
93
|
+
fs.watch(inputPath, eventType => {
|
|
94
|
+
if (eventType === 'change') {
|
|
95
|
+
readAndProcessCSS()
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
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 }
|