compile-css 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ {
2
+ // 使用 IntelliSense 了解相关属性。
3
+ // 悬停以查看现有属性的描述。
4
+ // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Listen for Xdebug",
9
+ "type": "php",
10
+ "request": "launch",
11
+ "port": 9003
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://cdn.statically.io/gh/nguyenngoclongdev/cdn/main/schema/v11/terminal-keeper.json",
3
+ "theme": "tribe",
4
+ "active": "default",
5
+ "activateOnStartup": true,
6
+ "keepExistingTerminals": false,
7
+ "sessions": {
8
+ "default": [
9
+ {
10
+ "name": "cmd",
11
+ "autoExecuteCommands": false,
12
+ "icon": "person",
13
+ "color": "terminal.ansiGreen",
14
+ "commands": []
15
+ },
16
+ [
17
+ {
18
+ "name": "compileCss",
19
+ "commands": [
20
+ "npm run compileCss"
21
+ ]
22
+ },
23
+ {
24
+ "name": "cmd",
25
+ "commands": []
26
+ }
27
+ ]
28
+ ]
29
+ }
30
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "php.validate.executablePath": "D:/greenSoftware/phpEnv/php/php-7.4/php.exe",
3
+ "terminal.integrated.env.windows": {
4
+ "PATH": "D:/greenSoftware/phpEnv/php/php-7.4/;${env:PATH}"
5
+ },
6
+ }
package/README.md CHANGED
@@ -1,71 +1,126 @@
1
- # CSS Compile Tool
1
+ # CSS 编译工具
2
2
 
3
- A powerful CSS compilation tool that supports SCSS, PostCSS, and TailwindCSS with file watching capabilities.
3
+ 支持 SCSSPostCSSTailwindCSS CSS 编译工具,自带文件监听功能。
4
4
 
5
- ## Installation
5
+ ## 安装
6
6
 
7
7
  ```bash
8
8
  npm install -g compile-css
9
- # or
9
+ #
10
10
  npm install --save-dev compile-css
11
11
  ```
12
12
 
13
- ## Usage
13
+ ## 使用方法
14
14
 
15
- ### Command Line
15
+ 直接在项目根目录运行:
16
16
 
17
17
  ```bash
18
- # Compile once
19
18
  compile-css
20
-
21
- # Watch for changes
22
- compile-css --watch
23
-
24
- # Use custom config
25
- compile-css --config ./my-config.js
26
19
  ```
27
20
 
28
- ### Programmatic Usage
21
+ 工具会自动读取根目录下的 `compileCssConfig.js` 配置文件,启动文件监听并开始编译。
29
22
 
30
- ```javascript
31
- const compileCss = require('compile-css');
23
+ ## 配置说明
32
24
 
33
- // Use default config
34
- compileCss();
25
+ 在项目根目录创建 `compileCssConfig.js` 文件。
35
26
 
36
- // With custom options
37
- compileCss({
38
- watch: true,
39
- config: './custom-config.js'
40
- });
41
- ```
27
+ ### 配置格式
42
28
 
43
- ## Configuration
29
+ 支持两种配置格式,**推荐使用 `presets` 多套配置**。
44
30
 
45
- Create a `compileCssConfig.js` file:
31
+ ### 单套配置(`paths`)
32
+
33
+ 适合只有一个 HTML 模板的简单项目:
46
34
 
47
35
  ```javascript
48
36
  const path = require('path');
49
37
 
50
38
  module.exports = {
51
39
  paths: {
52
- scss: path.resolve('./scss'),
53
- template: path.resolve('./html'),
54
- temp: path.resolve('./temp'),
55
- dist: path.resolve('./html', 'css')
40
+ scss: path.resolve('./scss'), // SCSS 源文件目录
41
+ template: path.resolve('./html'), // HTML 模板目录
42
+ temp: path.resolve('./temp'), // 编译临时目录
43
+ dist: path.resolve('./html', 'css'), // 编译输出目录
44
+ scssIgnore: ['scss/common.scss'], // 忽略的 SCSS 文件
45
+ templateIgnore: [] // 忽略的 HTML 文件
56
46
  }
57
47
  };
58
48
  ```
59
49
 
60
- ## Features
50
+ ### 多套配置(`presets`,推荐)
51
+
52
+ 适合 PC 端 + 手机端等多套模板的项目,每套配置独立编译互不干扰:
53
+
54
+ ```javascript
55
+ const path = require('path');
56
+
57
+ module.exports = {
58
+ presets: [
59
+ {
60
+ name: 'pc', // 标识名称,用于日志输出
61
+ scss: path.resolve('./scss/pc'), // PC 端 SCSS 目录
62
+ template: path.resolve('./html/pc'), // PC 端 HTML 目录
63
+ temp: path.resolve('./temp/pc'), // PC 端临时目录
64
+ dist: path.resolve('./html/pc', 'css'), // PC 端输出目录
65
+ scssIgnore: [],
66
+ templateIgnore: []
67
+ },
68
+ {
69
+ name: 'mobile', // 手机端
70
+ scss: path.resolve('./scss/mobile'),
71
+ template: path.resolve('./html/mobile'),
72
+ temp: path.resolve('./temp/mobile'),
73
+ dist: path.resolve('./html/mobile', 'css'),
74
+ scssIgnore: [],
75
+ templateIgnore: []
76
+ }
77
+ ]
78
+ };
79
+ ```
80
+
81
+ ### 配置项说明
82
+
83
+ | 配置项 | 类型 | 必填 | 说明 |
84
+ |--------|------|------|------|
85
+ | `name` | `string` | 否 | 标识名称,仅 `presets` 模式下使用,用于控制台日志输出,方便区分不同套的编译信息 |
86
+ | `scss` | `string` | 是 | SCSS 源文件目录路径。工具会递归扫描该目录下所有非 `_` 开头的 `.scss` 文件作为入口文件进行编译 |
87
+ | `template` | `string` | 是 | HTML 模板目录路径。当该目录下的 HTML 文件发生变化时,会触发 `common.css` 重新编译,以更新 TailwindCSS 的工具类 |
88
+ | `temp` | `string` | 是 | 编译过程中的临时目录路径。SCSS 先编译为普通 CSS 存放到此目录,再交给 PostCSS 处理。**每次启动时会自动清空此目录** |
89
+ | `dist` | `string` | 是 | 最终编译产物的输出目录路径。经过 tailwindcss、autoprefixer、cssnano 处理后的 CSS 文件会输出到这里 |
90
+ | `scssIgnore` | `string[]` | 否 | SCSS 忽略列表。支持文件名、相对路径或正则表达式。被忽略的文件不会被当作入口文件编译。例如 `['scss/common.scss']` 或 `[/^scss\/lib\//]` |
91
+ | `templateIgnore` | `string[]` | 否 | HTML 忽略列表。支持文件名、相对路径或正则表达式。被忽略的 HTML 文件变化不会触发重新编译 |
92
+
93
+ ### 忽略规则说明
94
+
95
+ `scssIgnore` 和 `templateIgnore` 支持三种匹配方式:
96
+
97
+ - **完整相对路径**:`'scss/common.scss'` — 匹配项目根目录下 `scss/common.scss`
98
+ - **目录前缀**:`'scss/lib'` — 匹配 `scss/lib` 目录下的所有文件
99
+ - **文件名**:`'_variables.scss'` — 匹配所有名为 `_variables.scss` 的文件
100
+ - **正则表达式**:`/^scss\/lib\//` — 使用正则匹配相对路径
101
+
102
+ ### 注意事项
103
+
104
+ - `scss` 目录中以 `_` 开头的文件(如 `_variables.scss`)被视为模块文件,不会作为入口文件编译。但当模块文件发生变化时,会触发所有入口文件重新编译
105
+ - 每个 `preset` 的 `temp` 目录必须是唯一的,不能与其他 `preset` 共享目录
106
+ - 每个 `preset` 的 `temp` 目录在工具启动时会被自动清空重建,确保没有残留文件影响编译结果
107
+ - `tailwind.config.js` 必须放在项目根目录,工具启动时会自动加载
108
+ ```
109
+
110
+ ## 编译流程
111
+
112
+ ```
113
+ SCSS 文件 ──sass编译──▶ temp 目录(临时 CSS) ──tailwindcss + autoprefixer + cssnano──▶ dist 目录(最终 CSS)
114
+ ```
61
115
 
62
- - SCSS compilation
63
- - PostCSS processing
64
- - TailwindCSS integration
65
- - ✅ File watching
66
- - ✅ Auto-prefixing
67
- - ✅ CSS optimization
116
+ 1. 监听 SCSS 文件变化,通过 `sass` 编译到 `temp` 目录
117
+ 2. 监听 `temp` 目录的 CSS 文件变化,通过 PostCSS(tailwindcss + autoprefixer + cssnano)编译到 `dist` 目录
118
+ 3. 监听 HTML 文件变化,重新编译 `common.css` 以更新 TailwindCSS 的工具类
68
119
 
69
- ## License
120
+ ## 功能特性
70
121
 
71
- MIT
122
+ - SCSS 编译
123
+ - PostCSS 处理(tailwindcss、autoprefixer、cssnano)
124
+ - 文件变化自动监听编译
125
+ - 支持多套模板配置(PC、手机等)
126
+ - 启动时自动清理临时目录
package/compileCss.js CHANGED
@@ -22,7 +22,7 @@ function loadUserConfig(configName) {
22
22
  }
23
23
 
24
24
  // 加载编译配置(优先用户项目,回退到包默认)
25
- const config = loadUserConfig('compileCssConfig.js') || {
25
+ const rawConfig = loadUserConfig('compileCssConfig.js') || {
26
26
  paths: {
27
27
  scss: path.resolve('./scss'),
28
28
  template: path.resolve('./html'),
@@ -31,10 +31,24 @@ const config = loadUserConfig('compileCssConfig.js') || {
31
31
  }
32
32
  };
33
33
 
34
- const scss = config.paths.scss;
35
- const template = config.paths.template;
36
- const temp = config.paths.temp;
37
- const dist = config.paths.dist;
34
+ // 兼容旧版单套 paths 配置,自动转换为 presets
35
+ let presets;
36
+ if (rawConfig.presets) {
37
+ presets = rawConfig.presets;
38
+ } else if (rawConfig.paths) {
39
+ presets = [{
40
+ name: 'default',
41
+ scss: rawConfig.paths.scss,
42
+ template: rawConfig.paths.template,
43
+ temp: rawConfig.paths.temp,
44
+ dist: rawConfig.paths.dist,
45
+ scssIgnore: rawConfig.paths.scssIgnore || [],
46
+ templateIgnore: rawConfig.paths.templateIgnore || []
47
+ }];
48
+ } else {
49
+ console.error('错误:配置文件格式不正确,请提供 paths 或 presets 配置。');
50
+ process.exit(1);
51
+ }
38
52
 
39
53
  // 加载Tailwind配置(必须由用户提供)
40
54
  const toption = loadUserConfig('tailwind.config.js');
@@ -43,14 +57,33 @@ if (!toption) {
43
57
  process.exit(1);
44
58
  }
45
59
 
60
+ /**
61
+ * 检查文件是否被忽略
62
+ * @param {string} filePath 文件路径
63
+ * @param {[string]} ignoreList 忽略列表,每个元素可以是字符串或正则表达式
64
+ * @return {boolean} 是否被忽略
65
+ */
66
+ function isIgnored(filePath, ignoreList) {
67
+ const relative = path.relative(process.cwd(), filePath);
68
+ return ignoreList.some(ignored => {
69
+ if (typeof ignored === 'string') {
70
+ return relative === ignored || relative.startsWith(ignored + path.sep) || path.basename(filePath) === ignored;
71
+ }
72
+ if (ignored instanceof RegExp) {
73
+ return ignored.test(relative);
74
+ }
75
+ return false;
76
+ });
77
+ }
78
+
46
79
  /**
47
80
  * 获取入口文件列表
48
81
  * @param {string|[string]} entrance 入口 文件路径或文件路径数组,可以是文件也可以是目录,目录要递归查找
82
+ * @param {[string]} ignoreList 忽略列表
49
83
  * @return {[string]} 返回入口文件列表
50
84
  */
51
- function getEntranceFiles(entrance) {
85
+ function getEntranceFiles(entrance, ignoreList) {
52
86
  const result = new Set();
53
-
54
87
  const entrances = Array.isArray(entrance) ? entrance : [entrance];
55
88
 
56
89
  function walk(p) {
@@ -61,15 +94,14 @@ function getEntranceFiles(entrance) {
61
94
  if (stat.isFile()) {
62
95
  const ext = path.extname(p);
63
96
  const name = path.basename(p);
64
-
65
- // 只收集非 "_" 开头的 scss 文件
66
- if (ext === '.scss' && !name.startsWith('_')) {
97
+ if (ext === '.scss' && !name.startsWith('_') && !isIgnored(p, ignoreList)) {
67
98
  result.add(path.resolve(p));
68
99
  }
69
100
  return;
70
101
  }
71
102
 
72
103
  if (stat.isDirectory()) {
104
+ if (isIgnored(p, ignoreList)) return;
73
105
  const files = fs.readdirSync(p);
74
106
  for (const file of files) {
75
107
  walk(path.join(p, file));
@@ -139,67 +171,74 @@ function postcssCompile(file, output, tcontent) {
139
171
 
140
172
  }
141
173
 
142
- let paths = [
143
- path.resolve(template),
144
- path.resolve(scss),
145
- path.resolve(temp),
146
- ];
147
- var watcher = chokidar.watch(paths, {
148
- ignored: [
149
- // watchRootPath+'/ThinkPHP',
150
- ],
151
- persistent: true,
152
- // followSymlinks:false
153
- })
154
- .on('all', (eventName, pathfile, stats) => {
155
- try {
156
- console.log(eventName, pathfile)
157
- if (['add', 'change'].includes(eventName)) { //新增或者修改文件 进行编译操作
158
- if (pathfile.endsWith('.scss')) {
159
- // 获取文件名
160
- let fileName = path.basename(pathfile);
161
- let entranceFiles = [];
162
- if(fileName.startsWith('_')){ //如果是模块,编译所有入口文件
163
- entranceFiles = getEntranceFiles(scss);
164
- }else{ //如果是普通文件,编译该文件
165
- entranceFiles = [pathfile];
174
+ // 为每个 preset 启动独立的 watcher
175
+ presets.forEach(function (preset) {
176
+ var scssDir = preset.scss;
177
+ var templateDir = preset.template;
178
+ var tempDir = preset.temp;
179
+ var distDir = preset.dist;
180
+ var scssIgnore = preset.scssIgnore || [];
181
+ var templateIgnore = preset.templateIgnore || [];
182
+ var presetName = preset.name || 'default';
183
+
184
+ // 启动时清理并重新创建 temp 目录
185
+ if (fs.existsSync(tempDir)) {
186
+ fs.rmSync(tempDir, { recursive: true, force: true });
187
+ }
188
+ fs.mkdirSync(tempDir, { recursive: true });
189
+
190
+ var watchPaths = [
191
+ path.resolve(templateDir),
192
+ path.resolve(scssDir),
193
+ path.resolve(tempDir),
194
+ ];
195
+
196
+ chokidar.watch(watchPaths, {
197
+ ignored: [
198
+ ...scssIgnore.map(function (i) { return path.resolve(process.cwd(), i); }),
199
+ ...templateIgnore.map(function (i) { return path.resolve(process.cwd(), i); }),
200
+ ],
201
+ persistent: true,
202
+ })
203
+ .on('all', function (eventName, pathfile, stats) {
204
+ try {
205
+ console.log('[' + presetName + ']', eventName, pathfile)
206
+ if (['add', 'change'].includes(eventName)) {
207
+ if (pathfile.endsWith('.scss')) {
208
+ var fileName = path.basename(pathfile);
209
+ var entranceFiles = [];
210
+ if (fileName.startsWith('_')) {
211
+ entranceFiles = getEntranceFiles(scssDir, scssIgnore);
212
+ } else {
213
+ entranceFiles = [pathfile];
214
+ }
215
+
216
+ entranceFiles.forEach(function (entranceFile) {
217
+ var output = entranceFile.replace(scssDir, tempDir);
218
+ output = output.replace(/\.scss$/, '.css');
219
+ sassCompile(entranceFile, output);
220
+ });
166
221
  }
167
-
168
- // 编译入口文件
169
- entranceFiles.forEach(entranceFile => {
170
- let output = '';
171
- output = entranceFile.replace(scss, temp);
172
- //将文件扩展名改为css
173
- output = output.replace(/\.scss$/, '.css');
174
- sassCompile(entranceFile, output)
175
- });
176
-
177
- }
178
-
179
-
180
- if (pathfile.endsWith('.css')) {
181
- let output = '';
182
- //输出的目录结构应该保持和scss目录结构 或者 temp目录结构一致
183
- //如果是来源时scssDir目录结构,那么输出的目录结构应该是 distDir 目录结构
184
- let tcontent = [];
185
- tcontent = [path.resolve(template, '**/*.{html,htm}')];
186
-
187
- output = pathfile.replace(temp, dist);
188
- postcssCompile(pathfile, output, tcontent)
189
- }
190
222
 
223
+ if (pathfile.endsWith('.css')) {
224
+ //输出的目录结构应该保持和scss目录结构 或者 temp目录结构一致
225
+ //如果来源是scssDir目录,那么输出的目录应该是 distDir
226
+ var tcontent = [path.resolve(templateDir, '**/*.{html,htm}')];
227
+ var output = pathfile.replace(tempDir, distDir);
228
+ postcssCompile(pathfile, output, tcontent);
229
+ }
191
230
 
192
- if (pathfile.endsWith('.html')) {
193
- let tcontent;
194
- let input = '';
195
- let output = '';
196
- tcontent = [path.resolve(template, '**/*.{html,htm}')];
197
- input = path.resolve(temp, 'common.css');
198
- output = path.resolve(dist, 'common.css');
199
- postcssCompile(input, output, tcontent);
231
+ if (pathfile.endsWith('.html') && !isIgnored(pathfile, templateIgnore)) {
232
+ var tcontent = [path.resolve(templateDir, '**/*.{html,htm}')];
233
+ var input = path.resolve(tempDir, 'common.css');
234
+ var output = path.resolve(distDir, 'common.css');
235
+ postcssCompile(input, output, tcontent);
236
+ }
200
237
  }
238
+ } catch (e) {
239
+ console.log(e);
201
240
  }
202
- } catch (e) {
203
- console.log(e)
204
- }
205
- })
241
+ });
242
+
243
+ console.log('[' + presetName + '] 监听已启动: scss=' + scssDir + ', template=' + templateDir);
244
+ });
@@ -1,10 +1,36 @@
1
1
  const path = require('path');
2
2
 
3
+ // module.exports = {
4
+ // paths: {
5
+ // scss: path.resolve('./scss'), // scss文件目录
6
+ // template: path.resolve('./html'), // html文件目录
7
+ // temp: path.resolve('./temp'), //编译过程中的临时文件目录
8
+ // dist: path.resolve('./html', 'css'), //编译后的css文件目录
9
+ // scssIgnore: ['scss/common.scss'], // 忽略的scss文件名(可以是文件名或目录名)
10
+ // templateIgnore: [] // 忽略的html文件(可以是文件名或目录名)
11
+ // }
12
+ // };
13
+
14
+ // 多套配置
3
15
  module.exports = {
4
- paths: {
5
- scss: path.resolve('./scss'),
6
- template: path.resolve('./html'),
7
- temp: path.resolve('./temp'),
8
- dist: path.resolve('./html', 'css')
9
- }
10
- };
16
+ presets: [
17
+ {
18
+ name: 'pc', // 标识名称,用于日志
19
+ scss: path.resolve('./scss/'),
20
+ template: path.resolve('./html/'),
21
+ temp: path.resolve('./temp/pc'),
22
+ dist: path.resolve('html/css'),
23
+ scssIgnore: [],
24
+ templateIgnore: []
25
+ },
26
+ {
27
+ name: 'mobile',
28
+ scss: path.resolve('./scss/mobile'),
29
+ template: path.resolve('./html/mobile'),
30
+ temp: path.resolve('./temp/mobile'),
31
+ dist: path.resolve('html', 'mobile/css'),
32
+ scssIgnore: [],
33
+ templateIgnore: []
34
+ }
35
+ ]
36
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compile-css",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A CSS compilation tool that supports SCSS, PostCSS, and TailwindCSS",
5
5
  "main": "compileCss.js",
6
6
  "bin": {
@@ -48,4 +48,4 @@
48
48
  "devDependencies": {
49
49
  "requirejs": "^2.3.8"
50
50
  }
51
- }
51
+ }