balm-core 5.2.0 → 6.0.0-alpha.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/CHANGELOG.md +16 -0
- package/dist/index.cjs +2625 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +569 -0
- package/dist/index.d.ts +569 -0
- package/dist/index.js +2527 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -123
- package/src/balm.ts +108 -0
- package/src/bundler/esbuild.ts +47 -0
- package/src/bundler/index.ts +3 -0
- package/src/bundler/rollup.ts +45 -0
- package/src/bundler/webpack.ts +124 -0
- package/src/config/constants.ts +12 -0
- package/src/config/defaults.ts +209 -0
- package/src/config/index.ts +112 -0
- package/src/hooks/index.ts +224 -0
- package/src/index.ts +16 -0
- package/src/pipeline/file.ts +69 -0
- package/src/pipeline/index.ts +10 -0
- package/src/pipeline/pipeline.ts +135 -0
- package/src/pipeline/transforms/cache.ts +146 -0
- package/src/pipeline/transforms/htmlmin.ts +18 -0
- package/src/pipeline/transforms/less.ts +75 -0
- package/src/pipeline/transforms/postcss.ts +43 -0
- package/src/pipeline/transforms/rename.ts +37 -0
- package/src/pipeline/transforms/replace.ts +30 -0
- package/src/pipeline/transforms/sass.ts +106 -0
- package/src/pipeline/transforms/terser.ts +20 -0
- package/src/runner/dag.ts +77 -0
- package/src/runner/task.ts +38 -0
- package/src/shims.d.ts +5 -0
- package/src/tasks/cache.ts +72 -0
- package/src/tasks/clean.ts +21 -0
- package/src/tasks/copy.ts +36 -0
- package/src/tasks/ftp.ts +90 -0
- package/src/tasks/html.ts +232 -0
- package/src/tasks/index.ts +14 -0
- package/src/tasks/publish.ts +71 -0
- package/src/tasks/pwa.ts +99 -0
- package/src/tasks/remove.ts +24 -0
- package/src/tasks/replace.ts +34 -0
- package/src/tasks/script.ts +28 -0
- package/src/tasks/server.ts +183 -0
- package/src/tasks/static.ts +104 -0
- package/src/tasks/style.ts +57 -0
- package/src/tasks/zip.ts +65 -0
- package/src/types/index.ts +202 -0
- package/src/utilities/file.ts +120 -0
- package/src/utilities/logger.ts +63 -0
- package/src/utilities/utils.ts +46 -0
- package/src/utilities/workspace.ts +38 -0
- package/src/watcher/index.ts +100 -0
- package/tsconfig.json +8 -0
- package/tsup.config.ts +12 -0
- package/README.md +0 -196
- package/index.d.ts +0 -360
- package/lib/balm.js +0 -49
- package/lib/bootstrap/check_config.js +0 -43
- package/lib/bootstrap/index.js +0 -87
- package/lib/bundler/esbuild/build.js +0 -26
- package/lib/bundler/esbuild/index.js +0 -7
- package/lib/bundler/esbuild/options.js +0 -7
- package/lib/bundler/esbuild/transform.js +0 -36
- package/lib/bundler/rollup/build.js +0 -52
- package/lib/bundler/rollup/entry.js +0 -28
- package/lib/bundler/rollup/index.js +0 -20
- package/lib/bundler/rollup/output.js +0 -20
- package/lib/bundler/rollup/plugins.js +0 -31
- package/lib/bundler/webpack/config/common.js +0 -135
- package/lib/bundler/webpack/config/dev.js +0 -12
- package/lib/bundler/webpack/config/env.js +0 -67
- package/lib/bundler/webpack/config/index.js +0 -6
- package/lib/bundler/webpack/config/prod.js +0 -39
- package/lib/bundler/webpack/config/regex.js +0 -10
- package/lib/bundler/webpack/entry.js +0 -65
- package/lib/bundler/webpack/index.js +0 -32
- package/lib/bundler/webpack/loaders.js +0 -50
- package/lib/bundler/webpack/output.js +0 -41
- package/lib/bundler/webpack/rules/asset.js +0 -33
- package/lib/bundler/webpack/rules/babel.js +0 -19
- package/lib/bundler/webpack/rules/css.js +0 -109
- package/lib/bundler/webpack/rules/html.js +0 -15
- package/lib/bundler/webpack/rules/index.js +0 -10
- package/lib/config/assets.js +0 -30
- package/lib/config/constants.js +0 -14
- package/lib/config/env.js +0 -35
- package/lib/config/extras.js +0 -6
- package/lib/config/ftp.js +0 -6
- package/lib/config/globals.js +0 -43
- package/lib/config/html.js +0 -22
- package/lib/config/images.js +0 -4
- package/lib/config/index.js +0 -63
- package/lib/config/logs.js +0 -11
- package/lib/config/paths.js +0 -46
- package/lib/config/pwa.js +0 -24
- package/lib/config/roots.js +0 -9
- package/lib/config/scripts.js +0 -162
- package/lib/config/server.js +0 -84
- package/lib/config/spinner.js +0 -9
- package/lib/config/styles.js +0 -67
- package/lib/hello.js +0 -19
- package/lib/hooks/index.js +0 -94
- package/lib/hooks/maker.js +0 -59
- package/lib/index.js +0 -5
- package/lib/middlewares/history.js +0 -6
- package/lib/middlewares/index.js +0 -11
- package/lib/middlewares/proxy.js +0 -28
- package/lib/middlewares/webpack.js +0 -26
- package/lib/plugins/htmlmin.js +0 -39
- package/lib/plugins/imagemin.js +0 -95
- package/lib/plugins/index.js +0 -27
- package/lib/plugins/jsmin.js +0 -37
- package/lib/plugins/less.js +0 -97
- package/lib/plugins/plumber.js +0 -87
- package/lib/plugins/postcss-plugins.js +0 -13
- package/lib/plugins/postcss.js +0 -117
- package/lib/plugins/rename.js +0 -51
- package/lib/plugins/replace.js +0 -91
- package/lib/plugins/sass-legacy.js +0 -131
- package/lib/plugins/sass.js +0 -134
- package/lib/plugins/sftp.js +0 -288
- package/lib/tasks/default.js +0 -46
- package/lib/tasks/foundation/balm.js +0 -72
- package/lib/tasks/foundation/balm_style.js +0 -65
- package/lib/tasks/foundation/index.js +0 -10
- package/lib/tasks/index.js +0 -48
- package/lib/tasks/private/build.js +0 -18
- package/lib/tasks/private/cache.js +0 -31
- package/lib/tasks/private/clean.js +0 -69
- package/lib/tasks/private/end.js +0 -24
- package/lib/tasks/private/extra.js +0 -35
- package/lib/tasks/private/font.js +0 -15
- package/lib/tasks/private/image.js +0 -37
- package/lib/tasks/private/index.js +0 -34
- package/lib/tasks/private/lint.js +0 -20
- package/lib/tasks/private/media.js +0 -15
- package/lib/tasks/private/modernizr.js +0 -59
- package/lib/tasks/private/pwa-cache.js +0 -32
- package/lib/tasks/private/script.js +0 -9
- package/lib/tasks/private/sprite.js +0 -105
- package/lib/tasks/private/start.js +0 -16
- package/lib/tasks/private/style.js +0 -9
- package/lib/tasks/private/workbox-sw.js +0 -15
- package/lib/tasks/public/copy.js +0 -16
- package/lib/tasks/public/esbuild.js +0 -18
- package/lib/tasks/public/ftp.js +0 -39
- package/lib/tasks/public/html.js +0 -65
- package/lib/tasks/public/index.js +0 -38
- package/lib/tasks/public/jsmin.js +0 -23
- package/lib/tasks/public/less.js +0 -21
- package/lib/tasks/public/postcss.js +0 -16
- package/lib/tasks/public/publish.js +0 -51
- package/lib/tasks/public/pwa.js +0 -84
- package/lib/tasks/public/remove.js +0 -46
- package/lib/tasks/public/replace.js +0 -26
- package/lib/tasks/public/rollup.js +0 -17
- package/lib/tasks/public/sass.js +0 -27
- package/lib/tasks/public/server.js +0 -130
- package/lib/tasks/public/url.js +0 -35
- package/lib/tasks/public/version.js +0 -23
- package/lib/tasks/public/webpack.js +0 -39
- package/lib/tasks/public/zip.js +0 -19
- package/lib/utilities/address.js +0 -55
- package/lib/utilities/cache-core.js +0 -66
- package/lib/utilities/color.js +0 -27
- package/lib/utilities/compiling.js +0 -24
- package/lib/utilities/detect-port.js +0 -100
- package/lib/utilities/escape-string-regexp.js +0 -10
- package/lib/utilities/file.js +0 -70
- package/lib/utilities/index.js +0 -8
- package/lib/utilities/loading.js +0 -37
- package/lib/utilities/logger.js +0 -99
- package/lib/utilities/merge-stream.js +0 -38
- package/lib/utilities/namespace.js +0 -11
- package/lib/utilities/public-url.js +0 -37
- package/lib/utilities/replacestream.js +0 -106
- package/lib/utilities/typeof.js +0 -5
- package/lib/utilities/utils.js +0 -43
- package/tslib/balm.js +0 -44
- package/tslib/bootstrap/check_config.js +0 -36
- package/tslib/bootstrap/index.js +0 -82
- package/tslib/bundler/esbuild/build.js +0 -30
- package/tslib/bundler/esbuild/index.js +0 -11
- package/tslib/bundler/esbuild/options.js +0 -7
- package/tslib/bundler/esbuild/transform.js +0 -38
- package/tslib/bundler/rollup/build.js +0 -17
- package/tslib/bundler/rollup/entry.js +0 -24
- package/tslib/bundler/rollup/index.js +0 -21
- package/tslib/bundler/rollup/output.js +0 -23
- package/tslib/bundler/rollup/plugins.js +0 -27
- package/tslib/bundler/webpack/config/common.js +0 -130
- package/tslib/bundler/webpack/config/dev.js +0 -14
- package/tslib/bundler/webpack/config/env.js +0 -44
- package/tslib/bundler/webpack/config/index.js +0 -8
- package/tslib/bundler/webpack/config/prod.js +0 -43
- package/tslib/bundler/webpack/config/regex.js +0 -10
- package/tslib/bundler/webpack/entry.js +0 -68
- package/tslib/bundler/webpack/index.js +0 -30
- package/tslib/bundler/webpack/loaders.js +0 -51
- package/tslib/bundler/webpack/output.js +0 -41
- package/tslib/bundler/webpack/rules/asset.js +0 -33
- package/tslib/bundler/webpack/rules/babel.js +0 -16
- package/tslib/bundler/webpack/rules/css.js +0 -95
- package/tslib/bundler/webpack/rules/html.js +0 -15
- package/tslib/bundler/webpack/rules/index.js +0 -10
- package/tslib/config/assets.js +0 -24
- package/tslib/config/constants.js +0 -14
- package/tslib/config/env.js +0 -43
- package/tslib/config/extras.js +0 -6
- package/tslib/config/ftp.js +0 -6
- package/tslib/config/globals.js +0 -47
- package/tslib/config/html.js +0 -17
- package/tslib/config/images.js +0 -4
- package/tslib/config/index.js +0 -56
- package/tslib/config/logs.js +0 -6
- package/tslib/config/paths.js +0 -30
- package/tslib/config/pwa.js +0 -18
- package/tslib/config/roots.js +0 -8
- package/tslib/config/scripts.js +0 -93
- package/tslib/config/server.js +0 -33
- package/tslib/config/spinner.js +0 -10
- package/tslib/config/styles.js +0 -37
- package/tslib/hello.js +0 -19
- package/tslib/hooks/index.js +0 -75
- package/tslib/hooks/maker.js +0 -66
- package/tslib/index.js +0 -5
- package/tslib/middlewares/history.js +0 -12
- package/tslib/middlewares/index.js +0 -18
- package/tslib/middlewares/proxy.js +0 -27
- package/tslib/middlewares/webpack.js +0 -29
- package/tslib/plugins/htmlmin.js +0 -38
- package/tslib/plugins/imagemin.js +0 -97
- package/tslib/plugins/index.js +0 -27
- package/tslib/plugins/jsmin.js +0 -39
- package/tslib/plugins/less.js +0 -90
- package/tslib/plugins/plumber.js +0 -81
- package/tslib/plugins/postcss-plugins.js +0 -24
- package/tslib/plugins/postcss.js +0 -111
- package/tslib/plugins/rename.js +0 -51
- package/tslib/plugins/replace.js +0 -72
- package/tslib/plugins/sass-legacy.js +0 -95
- package/tslib/plugins/sass.js +0 -109
- package/tslib/plugins/sftp.js +0 -258
- package/tslib/tasks/default.js +0 -59
- package/tslib/tasks/foundation/balm.js +0 -75
- package/tslib/tasks/foundation/balm_style.js +0 -68
- package/tslib/tasks/foundation/index.js +0 -10
- package/tslib/tasks/index.js +0 -43
- package/tslib/tasks/private/build.js +0 -15
- package/tslib/tasks/private/cache.js +0 -48
- package/tslib/tasks/private/clean.js +0 -82
- package/tslib/tasks/private/end.js +0 -21
- package/tslib/tasks/private/extra.js +0 -34
- package/tslib/tasks/private/font.js +0 -12
- package/tslib/tasks/private/image.js +0 -42
- package/tslib/tasks/private/index.js +0 -34
- package/tslib/tasks/private/lint.js +0 -17
- package/tslib/tasks/private/media.js +0 -12
- package/tslib/tasks/private/modernizr.js +0 -54
- package/tslib/tasks/private/pwa-cache.js +0 -32
- package/tslib/tasks/private/script.js +0 -9
- package/tslib/tasks/private/sprite.js +0 -93
- package/tslib/tasks/private/start.js +0 -13
- package/tslib/tasks/private/style.js +0 -12
- package/tslib/tasks/private/workbox-sw.js +0 -15
- package/tslib/tasks/public/copy.js +0 -18
- package/tslib/tasks/public/esbuild.js +0 -18
- package/tslib/tasks/public/ftp.js +0 -39
- package/tslib/tasks/public/html.js +0 -75
- package/tslib/tasks/public/index.js +0 -38
- package/tslib/tasks/public/jsmin.js +0 -24
- package/tslib/tasks/public/less.js +0 -21
- package/tslib/tasks/public/postcss.js +0 -16
- package/tslib/tasks/public/publish.js +0 -50
- package/tslib/tasks/public/pwa.js +0 -87
- package/tslib/tasks/public/remove.js +0 -44
- package/tslib/tasks/public/replace.js +0 -27
- package/tslib/tasks/public/rollup.js +0 -17
- package/tslib/tasks/public/sass.js +0 -27
- package/tslib/tasks/public/server.js +0 -129
- package/tslib/tasks/public/url.js +0 -35
- package/tslib/tasks/public/version.js +0 -27
- package/tslib/tasks/public/webpack.js +0 -41
- package/tslib/tasks/public/zip.js +0 -19
- package/tslib/utilities/address.js +0 -48
- package/tslib/utilities/cache-core.js +0 -57
- package/tslib/utilities/color.js +0 -33
- package/tslib/utilities/compiling.js +0 -16
- package/tslib/utilities/detect-port.js +0 -91
- package/tslib/utilities/escape-string-regexp.js +0 -7
- package/tslib/utilities/file.js +0 -78
- package/tslib/utilities/index.js +0 -8
- package/tslib/utilities/loading.js +0 -25
- package/tslib/utilities/logger.js +0 -92
- package/tslib/utilities/merge-stream.js +0 -34
- package/tslib/utilities/namespace.js +0 -12
- package/tslib/utilities/public-url.js +0 -31
- package/tslib/utilities/replacestream.js +0 -112
- package/tslib/utilities/typeof.js +0 -8
- package/tslib/utilities/utils.js +0 -38
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CopyTask,
|
|
3
|
+
RemoveTask,
|
|
4
|
+
ReplaceTask,
|
|
5
|
+
PublishTask,
|
|
6
|
+
PwaTask,
|
|
7
|
+
ZipTask,
|
|
8
|
+
FtpTask,
|
|
9
|
+
ServerTask
|
|
10
|
+
} from '../tasks/index.js';
|
|
11
|
+
import { FunctionTask } from '../runner/task.js';
|
|
12
|
+
import { Pipeline } from '../pipeline/pipeline.js';
|
|
13
|
+
import { transformSass } from '../pipeline/transforms/sass.js';
|
|
14
|
+
import { transformLess } from '../pipeline/transforms/less.js';
|
|
15
|
+
import { transformPostcss } from '../pipeline/transforms/postcss.js';
|
|
16
|
+
import { runWebpack } from '../bundler/webpack.js';
|
|
17
|
+
import { runRollup } from '../bundler/rollup.js';
|
|
18
|
+
import { runEsbuild } from '../bundler/esbuild.js';
|
|
19
|
+
import { TaskDAG } from '../runner/dag.js';
|
|
20
|
+
import {
|
|
21
|
+
RenameOptions,
|
|
22
|
+
ReplaceOptions,
|
|
23
|
+
TemplateOption,
|
|
24
|
+
BalmConfig
|
|
25
|
+
} from '../types/index.js';
|
|
26
|
+
import { logger } from '../utilities/logger.js';
|
|
27
|
+
|
|
28
|
+
export class BalmHooks {
|
|
29
|
+
private dag: TaskDAG;
|
|
30
|
+
private _config: BalmConfig;
|
|
31
|
+
private recipeIndex = 0;
|
|
32
|
+
|
|
33
|
+
constructor(dag: TaskDAG, config: BalmConfig) {
|
|
34
|
+
this.dag = dag;
|
|
35
|
+
this._config = config;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get config(): BalmConfig {
|
|
39
|
+
return this._config;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get env() {
|
|
43
|
+
return this._config.env;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private addRecipeTask(fn: (config: BalmConfig) => Promise<void> | void): void {
|
|
47
|
+
this.recipeIndex++;
|
|
48
|
+
const taskName = `recipe:${this.recipeIndex}`;
|
|
49
|
+
this.dag.registerTask(new FunctionTask(taskName, fn));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
copy(
|
|
53
|
+
input: string | string[],
|
|
54
|
+
output: string,
|
|
55
|
+
options: { rename?: RenameOptions | string | Function } = {}
|
|
56
|
+
): this {
|
|
57
|
+
this.addRecipeTask(async (config) => {
|
|
58
|
+
const task = new CopyTask({ input, output, rename: options.rename });
|
|
59
|
+
await task.run(config);
|
|
60
|
+
});
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
remove(target: string | string[]): this {
|
|
65
|
+
this.addRecipeTask(async (config) => {
|
|
66
|
+
const task = new RemoveTask(target);
|
|
67
|
+
await task.run(config);
|
|
68
|
+
});
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
replace(
|
|
73
|
+
input: string | string[],
|
|
74
|
+
output: string,
|
|
75
|
+
options: ReplaceOptions | ReplaceOptions[]
|
|
76
|
+
): this {
|
|
77
|
+
this.addRecipeTask(async (config) => {
|
|
78
|
+
const task = new ReplaceTask({ input, output, options });
|
|
79
|
+
await task.run(config);
|
|
80
|
+
});
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
sass(input: string | string[], output: string, options = {}): this {
|
|
85
|
+
this.addRecipeTask(async (config) => {
|
|
86
|
+
const pipeline = Pipeline.from(input, { cwd: config.workspace });
|
|
87
|
+
pipeline.pipe(transformSass(options));
|
|
88
|
+
pipeline.pipe(transformPostcss({ minify: config.env.isProd }));
|
|
89
|
+
await pipeline.dest(output);
|
|
90
|
+
});
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
less(input: string | string[], output: string, options = {}): this {
|
|
95
|
+
this.addRecipeTask(async (config) => {
|
|
96
|
+
const pipeline = Pipeline.from(input, { cwd: config.workspace });
|
|
97
|
+
pipeline.pipe(transformLess(options));
|
|
98
|
+
pipeline.pipe(transformPostcss({ minify: config.env.isProd }));
|
|
99
|
+
await pipeline.dest(output);
|
|
100
|
+
});
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
css(input: string | string[], output: string, options = {}): this {
|
|
105
|
+
this.addRecipeTask(async (config) => {
|
|
106
|
+
const pipeline = Pipeline.from(input, { cwd: config.workspace });
|
|
107
|
+
pipeline.pipe(transformPostcss({ minify: config.env.isProd, ...options }));
|
|
108
|
+
await pipeline.dest(output);
|
|
109
|
+
});
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
webpack(entry?: any, output?: string, customOptions: any = {}): this {
|
|
114
|
+
this.addRecipeTask(async (config) => {
|
|
115
|
+
const mergedOptions = {
|
|
116
|
+
...customOptions,
|
|
117
|
+
...(entry ? { entry } : {}),
|
|
118
|
+
output: {
|
|
119
|
+
...(output ? { path: output } : {}),
|
|
120
|
+
...customOptions.output
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
await runWebpack(config, mergedOptions);
|
|
124
|
+
});
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
rollup(
|
|
129
|
+
input?: any,
|
|
130
|
+
output?: any,
|
|
131
|
+
customInputOptions: any = {},
|
|
132
|
+
customOutputOptions: any = {}
|
|
133
|
+
): this {
|
|
134
|
+
this.addRecipeTask(async (config) => {
|
|
135
|
+
let inputOptions: any = {};
|
|
136
|
+
let outputOptions: any = {};
|
|
137
|
+
|
|
138
|
+
if (typeof input === 'object' && !Array.isArray(input) && input.input) {
|
|
139
|
+
inputOptions = { ...input, ...customInputOptions };
|
|
140
|
+
outputOptions =
|
|
141
|
+
typeof output === 'object'
|
|
142
|
+
? { ...output, ...customOutputOptions }
|
|
143
|
+
: { ...(output ? { dir: output } : {}), ...customOutputOptions };
|
|
144
|
+
} else {
|
|
145
|
+
inputOptions = { ...(input ? { input } : {}), ...customInputOptions };
|
|
146
|
+
outputOptions =
|
|
147
|
+
typeof output === 'object'
|
|
148
|
+
? { ...output, ...customOutputOptions }
|
|
149
|
+
: { ...(output ? { dir: output } : {}), ...customOutputOptions };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await runRollup(config, inputOptions, outputOptions);
|
|
153
|
+
});
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
esbuild(entryPoints?: any, outdir?: string, customOptions = {}): this {
|
|
158
|
+
this.addRecipeTask(async (config) => {
|
|
159
|
+
await runEsbuild(config, {
|
|
160
|
+
...(entryPoints ? { entryPoints } : {}),
|
|
161
|
+
...(outdir ? { outdir } : {}),
|
|
162
|
+
...customOptions
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
js(input?: any, output?: any, options = {}): this {
|
|
169
|
+
logger.warn('balm api', '`mix.js` is deprecated, please use `mix.webpack`/`mix.rollup`/`mix.esbuild` instead.');
|
|
170
|
+
return this.webpack(input, output, options);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
publish(
|
|
174
|
+
input?: string | TemplateOption[],
|
|
175
|
+
output?: string,
|
|
176
|
+
renameOptions?: string | Function | RenameOptions
|
|
177
|
+
): this {
|
|
178
|
+
this.addRecipeTask(async (config) => {
|
|
179
|
+
const task = new PublishTask({ input, output, renameOptions });
|
|
180
|
+
await task.run(config);
|
|
181
|
+
});
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
generateSW(options = {}): this {
|
|
186
|
+
this.addRecipeTask(async (config) => {
|
|
187
|
+
const task = new PwaTask({ mode: 'generateSW', options });
|
|
188
|
+
await task.run(config);
|
|
189
|
+
});
|
|
190
|
+
return this;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
injectManifest(options = {}): this {
|
|
194
|
+
this.addRecipeTask(async (config) => {
|
|
195
|
+
const task = new PwaTask({ mode: 'injectManifest', options });
|
|
196
|
+
await task.run(config);
|
|
197
|
+
});
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
ftp(localFiles?: string | string[], options = {}): this {
|
|
202
|
+
this.addRecipeTask(async (config) => {
|
|
203
|
+
const task = new FtpTask({ localFiles, options });
|
|
204
|
+
await task.run(config);
|
|
205
|
+
});
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
zip(input?: string | string[], output?: string, filename?: string): this {
|
|
210
|
+
this.addRecipeTask(async (config) => {
|
|
211
|
+
const task = new ZipTask({ input, output, filename });
|
|
212
|
+
await task.run(config);
|
|
213
|
+
});
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
serve(): this {
|
|
218
|
+
this.addRecipeTask(async (config) => {
|
|
219
|
+
const task = new ServerTask();
|
|
220
|
+
await task.run(config);
|
|
221
|
+
});
|
|
222
|
+
return this;
|
|
223
|
+
}
|
|
224
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { balm, Balm } from './balm.js';
|
|
2
|
+
|
|
3
|
+
export default balm;
|
|
4
|
+
export { Balm, balm };
|
|
5
|
+
export * from './types/index.js';
|
|
6
|
+
export * from './config/index.js';
|
|
7
|
+
export * from './runner/task.js';
|
|
8
|
+
export * from './runner/dag.js';
|
|
9
|
+
export * from './pipeline/index.js';
|
|
10
|
+
export * from './bundler/index.js';
|
|
11
|
+
export * from './tasks/index.js';
|
|
12
|
+
export * from './hooks/index.js';
|
|
13
|
+
export * from './utilities/logger.js';
|
|
14
|
+
export * from './utilities/file.js';
|
|
15
|
+
export * from './utilities/utils.js';
|
|
16
|
+
export * from './utilities/workspace.js';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
export interface VirtualFileOptions {
|
|
4
|
+
cwd: string;
|
|
5
|
+
base: string;
|
|
6
|
+
path: string;
|
|
7
|
+
contents: Buffer | string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class VirtualFile {
|
|
11
|
+
cwd: string;
|
|
12
|
+
base: string;
|
|
13
|
+
path: string;
|
|
14
|
+
contents: Buffer;
|
|
15
|
+
revPathOriginal?: string;
|
|
16
|
+
|
|
17
|
+
constructor(options: VirtualFileOptions) {
|
|
18
|
+
this.cwd = options.cwd;
|
|
19
|
+
this.base = options.base;
|
|
20
|
+
this.path = options.path;
|
|
21
|
+
this.contents = typeof options.contents === 'string'
|
|
22
|
+
? Buffer.from(options.contents)
|
|
23
|
+
: options.contents;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get relative(): string {
|
|
27
|
+
return path.relative(this.base, this.path);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get extname(): string {
|
|
31
|
+
return path.extname(this.path);
|
|
32
|
+
}
|
|
33
|
+
set extname(val: string) {
|
|
34
|
+
const dir = path.dirname(this.path);
|
|
35
|
+
const basename = path.basename(this.path, this.extname);
|
|
36
|
+
this.path = path.join(dir, `${basename}${val.startsWith('.') ? val : `.${val}`}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get basename(): string {
|
|
40
|
+
return path.basename(this.path);
|
|
41
|
+
}
|
|
42
|
+
set basename(val: string) {
|
|
43
|
+
const dir = path.dirname(this.path);
|
|
44
|
+
this.path = path.join(dir, val);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get stem(): string {
|
|
48
|
+
return path.basename(this.path, this.extname);
|
|
49
|
+
}
|
|
50
|
+
set stem(val: string) {
|
|
51
|
+
const dir = path.dirname(this.path);
|
|
52
|
+
this.path = path.join(dir, `${val}${this.extname}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
toString(encoding: BufferEncoding = 'utf8'): string {
|
|
56
|
+
return this.contents.toString(encoding);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
clone(): VirtualFile {
|
|
60
|
+
const cloned = new VirtualFile({
|
|
61
|
+
cwd: this.cwd,
|
|
62
|
+
base: this.base,
|
|
63
|
+
path: this.path,
|
|
64
|
+
contents: Buffer.from(this.contents)
|
|
65
|
+
});
|
|
66
|
+
cloned.revPathOriginal = this.revPathOriginal;
|
|
67
|
+
return cloned;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './file.js';
|
|
2
|
+
export * from './pipeline.js';
|
|
3
|
+
export * from './transforms/sass.js';
|
|
4
|
+
export * from './transforms/less.js';
|
|
5
|
+
export * from './transforms/postcss.js';
|
|
6
|
+
export * from './transforms/htmlmin.js';
|
|
7
|
+
export * from './transforms/terser.js';
|
|
8
|
+
export * from './transforms/replace.js';
|
|
9
|
+
export * from './transforms/rename.js';
|
|
10
|
+
export * from './transforms/cache.js';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fg from 'fast-glob';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import { VirtualFile } from './file.js';
|
|
5
|
+
import { file as fsUtil } from '../utilities/file.js';
|
|
6
|
+
|
|
7
|
+
export type TransformFn = (
|
|
8
|
+
file: VirtualFile
|
|
9
|
+
) => Promise<VirtualFile | VirtualFile[] | null | void> | VirtualFile | VirtualFile[] | null | void;
|
|
10
|
+
|
|
11
|
+
export interface PipelineOptions {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
base?: string;
|
|
14
|
+
allowEmpty?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Pipeline {
|
|
18
|
+
private cwd: string;
|
|
19
|
+
private base?: string;
|
|
20
|
+
private allowEmpty: boolean;
|
|
21
|
+
private files: VirtualFile[] = [];
|
|
22
|
+
private transforms: TransformFn[] = [];
|
|
23
|
+
|
|
24
|
+
constructor(options: PipelineOptions = {}) {
|
|
25
|
+
this.cwd = options.cwd || process.cwd();
|
|
26
|
+
this.base = options.base;
|
|
27
|
+
this.allowEmpty = options.allowEmpty ?? true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static from(
|
|
31
|
+
patterns: string | string[],
|
|
32
|
+
options: PipelineOptions = {}
|
|
33
|
+
): Pipeline {
|
|
34
|
+
const pipeline = new Pipeline(options);
|
|
35
|
+
return pipeline.src(patterns);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
src(patterns: string | string[], options: PipelineOptions = {}): this {
|
|
39
|
+
if (options.cwd) this.cwd = options.cwd;
|
|
40
|
+
if (options.base) this.base = options.base;
|
|
41
|
+
if (options.allowEmpty !== undefined) this.allowEmpty = options.allowEmpty;
|
|
42
|
+
|
|
43
|
+
this.transforms.push(async () => {
|
|
44
|
+
const patternArr = Array.isArray(patterns) ? patterns : [patterns];
|
|
45
|
+
const posPatterns = patternArr.filter((p) => !p.startsWith('!'));
|
|
46
|
+
const ignorePatterns = patternArr.filter((p) => p.startsWith('!')).map((p) => p.slice(1));
|
|
47
|
+
|
|
48
|
+
const fileList: VirtualFile[] = [];
|
|
49
|
+
for (const p of posPatterns) {
|
|
50
|
+
let patternBase = this.base;
|
|
51
|
+
if (!patternBase) {
|
|
52
|
+
const globIdx = p.search(/[*?{[\\]/);
|
|
53
|
+
if (globIdx !== -1) {
|
|
54
|
+
patternBase = path.resolve(this.cwd, p.slice(0, globIdx));
|
|
55
|
+
} else {
|
|
56
|
+
patternBase = path.resolve(this.cwd, path.dirname(p));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const matched = await fg(p, {
|
|
61
|
+
cwd: this.cwd,
|
|
62
|
+
absolute: true,
|
|
63
|
+
dot: true,
|
|
64
|
+
onlyFiles: true,
|
|
65
|
+
ignore: ignorePatterns
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
for (const filePath of matched) {
|
|
69
|
+
const buffer = await fs.readFile(filePath);
|
|
70
|
+
fileList.push(
|
|
71
|
+
new VirtualFile({
|
|
72
|
+
cwd: this.cwd,
|
|
73
|
+
base: patternBase,
|
|
74
|
+
path: filePath,
|
|
75
|
+
contents: buffer
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!fileList.length && !this.allowEmpty) {
|
|
82
|
+
throw new Error(`File not found with pattern: ${patterns}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.files = fileList;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
pipe(transform: TransformFn): this {
|
|
92
|
+
this.transforms.push(transform);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async process(): Promise<VirtualFile[]> {
|
|
97
|
+
let isSrcLoaded = false;
|
|
98
|
+
for (const transform of this.transforms) {
|
|
99
|
+
if (!isSrcLoaded) {
|
|
100
|
+
// Initial src loader
|
|
101
|
+
await transform(null as any);
|
|
102
|
+
isSrcLoaded = true;
|
|
103
|
+
} else {
|
|
104
|
+
if (this.files.length === 0) break;
|
|
105
|
+
const nextFiles: VirtualFile[] = [];
|
|
106
|
+
for (const file of this.files) {
|
|
107
|
+
const result = await transform(file);
|
|
108
|
+
if (result === undefined || result === file) {
|
|
109
|
+
nextFiles.push(file);
|
|
110
|
+
} else if (Array.isArray(result)) {
|
|
111
|
+
nextFiles.push(...result);
|
|
112
|
+
} else if (result !== null) {
|
|
113
|
+
nextFiles.push(result);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.files = nextFiles;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return this.files;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async dest(outDir: string): Promise<string[]> {
|
|
123
|
+
const files = await this.process();
|
|
124
|
+
const writtenPaths: string[] = [];
|
|
125
|
+
const absOutDir = path.isAbsolute(outDir) ? outDir : path.resolve(this.cwd, outDir);
|
|
126
|
+
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
const targetPath = path.resolve(absOutDir, file.relative);
|
|
129
|
+
await fsUtil.writeFile(targetPath, file.contents);
|
|
130
|
+
writtenPaths.push(targetPath);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return writtenPaths;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import picomatch from 'picomatch';
|
|
3
|
+
import { VirtualFile } from '../file.js';
|
|
4
|
+
import { file as fsUtil } from '../../utilities/file.js';
|
|
5
|
+
|
|
6
|
+
export interface CacheTransformOptions {
|
|
7
|
+
fileNameManifest?: string;
|
|
8
|
+
dontRenameFile?: (string | RegExp)[];
|
|
9
|
+
dontUpdateReference?: (string | RegExp)[];
|
|
10
|
+
hashLength?: number;
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function matchesAny(filePath: string, rules?: (string | RegExp)[]): boolean {
|
|
15
|
+
if (!rules || !rules.length) return false;
|
|
16
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
17
|
+
const baseName = path.basename(normalized);
|
|
18
|
+
for (const rawRule of rules) {
|
|
19
|
+
if (typeof rawRule === 'string') {
|
|
20
|
+
const rule = rawRule.replace(/\\/g, '/');
|
|
21
|
+
const cleanRule = rule.replace(/^dist\//, '').replace(/^\.\/dist\//, '');
|
|
22
|
+
if (
|
|
23
|
+
normalized.endsWith(rule) ||
|
|
24
|
+
normalized.endsWith(cleanRule) ||
|
|
25
|
+
baseName === rule ||
|
|
26
|
+
baseName === cleanRule ||
|
|
27
|
+
baseName.endsWith(rule) ||
|
|
28
|
+
picomatch.isMatch(normalized, rule) ||
|
|
29
|
+
picomatch.isMatch(normalized, cleanRule) ||
|
|
30
|
+
picomatch.isMatch(normalized, `**/${cleanRule}`) ||
|
|
31
|
+
picomatch.isMatch(baseName, rule) ||
|
|
32
|
+
picomatch.isMatch(baseName, cleanRule)
|
|
33
|
+
) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
} else if (rawRule instanceof RegExp) {
|
|
37
|
+
if (rawRule.test(normalized) || rawRule.test(baseName)) return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class AssetRevisioner {
|
|
44
|
+
private options: CacheTransformOptions;
|
|
45
|
+
private manifest: Record<string, string> = {};
|
|
46
|
+
|
|
47
|
+
constructor(options: CacheTransformOptions = {}) {
|
|
48
|
+
const baseDontRename = [
|
|
49
|
+
'.html',
|
|
50
|
+
'favicon.ico',
|
|
51
|
+
'manifest.json',
|
|
52
|
+
'robots.txt',
|
|
53
|
+
'*.ico',
|
|
54
|
+
'workbox-sw.js',
|
|
55
|
+
'workbox-sw.js.map',
|
|
56
|
+
'service-worker.js',
|
|
57
|
+
'sw.js'
|
|
58
|
+
];
|
|
59
|
+
this.options = {
|
|
60
|
+
fileNameManifest: 'rev-manifest.json',
|
|
61
|
+
dontRenameFile: baseDontRename,
|
|
62
|
+
dontUpdateReference: [],
|
|
63
|
+
hashLength: 8,
|
|
64
|
+
...options
|
|
65
|
+
};
|
|
66
|
+
if (options.dontRenameFile) {
|
|
67
|
+
this.options.dontRenameFile = [
|
|
68
|
+
...baseDontRename,
|
|
69
|
+
...options.dontRenameFile
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
process(files: VirtualFile[]): VirtualFile[] {
|
|
75
|
+
const hashLength = this.options.hashLength || 8;
|
|
76
|
+
const outputFiles: VirtualFile[] = [];
|
|
77
|
+
|
|
78
|
+
// Phase 1: Calculate hashes and renames
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const origRelative = file.relative;
|
|
81
|
+
file.revPathOriginal = file.path;
|
|
82
|
+
|
|
83
|
+
// Check if file is already hashed (e.g. app.0e94aeee.js or chunk.22810145.js)
|
|
84
|
+
const alreadyHashed = /\.[a-f0-9]{8}$/i.test(file.stem);
|
|
85
|
+
|
|
86
|
+
const shouldRename =
|
|
87
|
+
!alreadyHashed &&
|
|
88
|
+
!matchesAny(file.path, this.options.dontRenameFile) &&
|
|
89
|
+
!matchesAny(file.relative, this.options.dontRenameFile);
|
|
90
|
+
|
|
91
|
+
if (shouldRename) {
|
|
92
|
+
const fileHash = fsUtil.hash(file.contents, hashLength);
|
|
93
|
+
const dir = path.dirname(file.path);
|
|
94
|
+
const newFilename = `${file.stem}.${fileHash}${file.extname}`;
|
|
95
|
+
file.path = path.join(dir, newFilename);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (alreadyHashed) {
|
|
99
|
+
const unhashedRelative = file.relative.replace(/\.[a-f0-9]{8}(\.[^.]+)$/i, '$1');
|
|
100
|
+
this.manifest[unhashedRelative] = file.relative;
|
|
101
|
+
}
|
|
102
|
+
this.manifest[origRelative] = file.relative;
|
|
103
|
+
outputFiles.push(file);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Phase 2: Rewrite references
|
|
107
|
+
const manifestEntries = Object.entries(this.manifest)
|
|
108
|
+
.filter(([orig, reved]) => orig !== reved)
|
|
109
|
+
.sort((a, b) => b[0].length - a[0].length);
|
|
110
|
+
|
|
111
|
+
for (const file of outputFiles) {
|
|
112
|
+
const shouldUpdate =
|
|
113
|
+
!matchesAny(file.path, this.options.dontUpdateReference) &&
|
|
114
|
+
!matchesAny(file.relative, this.options.dontUpdateReference);
|
|
115
|
+
|
|
116
|
+
if (shouldUpdate && /\.(html|css|js)$/i.test(file.extname)) {
|
|
117
|
+
let content = file.toString();
|
|
118
|
+
for (const [orig, reved] of manifestEntries) {
|
|
119
|
+
// Replace full relative path first
|
|
120
|
+
content = content.replaceAll(orig, reved);
|
|
121
|
+
|
|
122
|
+
// Replace basename with boundary check to avoid substring collision (e.g. .woff matching .woff2)
|
|
123
|
+
const origBase = path.basename(orig);
|
|
124
|
+
const revedBase = path.basename(reved);
|
|
125
|
+
const escapedBase = origBase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
126
|
+
const baseRegex = new RegExp(`${escapedBase}(?![a-zA-Z0-9_])`, 'g');
|
|
127
|
+
content = content.replace(baseRegex, revedBase);
|
|
128
|
+
}
|
|
129
|
+
file.contents = Buffer.from(content);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Phase 3: Add manifest file
|
|
134
|
+
const manifestName = this.options.fileNameManifest || 'rev-manifest.json';
|
|
135
|
+
const firstBase = files[0]?.base || process.cwd();
|
|
136
|
+
const manifestFile = new VirtualFile({
|
|
137
|
+
cwd: files[0]?.cwd || process.cwd(),
|
|
138
|
+
base: firstBase,
|
|
139
|
+
path: path.join(firstBase, manifestName),
|
|
140
|
+
contents: JSON.stringify(this.manifest, null, 2)
|
|
141
|
+
});
|
|
142
|
+
outputFiles.push(manifestFile);
|
|
143
|
+
|
|
144
|
+
return outputFiles;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { minify } from 'html-minifier-terser';
|
|
2
|
+
import { TransformFn } from '../pipeline.js';
|
|
3
|
+
import { logger } from '../../utilities/logger.js';
|
|
4
|
+
|
|
5
|
+
export function transformHtmlmin(options: Record<string, any> = {}): TransformFn {
|
|
6
|
+
return async (file) => {
|
|
7
|
+
if (!/\.html$/i.test(file.extname)) return file;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const minified = await minify(file.toString(), options);
|
|
11
|
+
file.contents = Buffer.from(minified);
|
|
12
|
+
return file;
|
|
13
|
+
} catch (err: any) {
|
|
14
|
+
logger.error('htmlmin', `Error minifying ${file.path}: ${err.message}`);
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import less from 'less';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { TransformFn } from '../pipeline.js';
|
|
4
|
+
import { logger } from '../../utilities/logger.js';
|
|
5
|
+
|
|
6
|
+
export interface LessTransformOptions {
|
|
7
|
+
paths?: string[];
|
|
8
|
+
alias?: Record<string, string>;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class AliasFileManager extends less.FileManager {
|
|
13
|
+
private alias: Record<string, string>;
|
|
14
|
+
|
|
15
|
+
constructor(alias: Record<string, string> = {}) {
|
|
16
|
+
super();
|
|
17
|
+
this.alias = alias;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
supports(filename: string): boolean {
|
|
21
|
+
const clean = filename.startsWith('~') ? filename.slice(1) : filename;
|
|
22
|
+
return Object.keys(this.alias).some((k) => clean === k || clean.startsWith(`${k}/`));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
loadFile(filename: string, currentDirectory: string, options: any, environment: any): Promise<any> {
|
|
26
|
+
const clean = filename.startsWith('~') ? filename.slice(1) : filename;
|
|
27
|
+
for (const [k, v] of Object.entries(this.alias)) {
|
|
28
|
+
if (clean === k) {
|
|
29
|
+
return super.loadFile(v, currentDirectory, options, environment);
|
|
30
|
+
} else if (clean.startsWith(`${k}/`)) {
|
|
31
|
+
const sub = clean.slice(k.length + 1);
|
|
32
|
+
return super.loadFile(path.join(v, sub), currentDirectory, options, environment);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return super.loadFile(filename, currentDirectory, options, environment);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function transformLess(options: LessTransformOptions = {}): TransformFn {
|
|
40
|
+
return async (file) => {
|
|
41
|
+
if (!/\.less$/i.test(file.extname)) return file;
|
|
42
|
+
if (path.basename(file.path).startsWith('_')) return null;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const paths = [
|
|
46
|
+
path.dirname(file.path),
|
|
47
|
+
path.resolve(file.cwd, 'node_modules'),
|
|
48
|
+
...(options.paths || [])
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const plugins = [...(options.plugins || [])];
|
|
52
|
+
if (options.alias && Object.keys(options.alias).length > 0) {
|
|
53
|
+
plugins.push({
|
|
54
|
+
install: (lessInstance: any, pluginManager: any) => {
|
|
55
|
+
pluginManager.addFileManager(new AliasFileManager(options.alias));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const result = await less.render(file.toString(), {
|
|
61
|
+
filename: file.path,
|
|
62
|
+
paths,
|
|
63
|
+
...options,
|
|
64
|
+
plugins
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
file.contents = Buffer.from(result.css);
|
|
68
|
+
file.extname = '.css';
|
|
69
|
+
return file;
|
|
70
|
+
} catch (err: any) {
|
|
71
|
+
logger.error('less', `Error compiling ${file.path}: ${err.message}`);
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|