balm-core 4.26.0 → 4.27.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/index.d.ts CHANGED
@@ -43,7 +43,9 @@ interface BalmStyles {
43
43
 
44
44
  // Sass
45
45
  export type SassOptions = import('sass').Options<'sync'>;
46
- export type SassImporter = import('sass').FileImporter<'sync'>;
46
+ export type CompileResult = import('sass').CompileResult;
47
+ export type LegacyOptions = import('sass').LegacyOptions<'sync'>;
48
+ export type LegacyResult = import('sass').LegacyResult;
47
49
 
48
50
  // Webpack
49
51
  export type WebpackEntry = import('webpack').Entry;
@@ -1,18 +1,23 @@
1
- import path from 'node:path';
2
1
  import fs from 'node:fs';
3
2
  import { pathToFileURL } from 'node:url';
4
3
  // Reference `gulp-sass@5.1.0`
5
4
  import { Transform } from 'node:stream';
5
+ import semver from 'semver';
6
6
  import * as sass from 'sass';
7
7
  import replaceExtension from 'replace-ext';
8
8
  import stripAnsi from 'strip-ansi';
9
9
  import applySourceMap from 'vinyl-sourcemaps-apply';
10
10
  import ansiColors from 'ansi-colors';
11
11
  process.env.BALM_CWD = process.env.INIT_CWD || process.cwd();
12
- const localSassModule = path.join(process.env.BALM_ROOT || process.env.BALM_CWD, 'node_modules', 'sass');
13
- const nodeLocalSassModule = path.join(localSassModule, 'sass.node.js');
14
- const defaultLocalSassModule = path.join(localSassModule, 'sass.default.js'); // For `npm i -D sass <= 1.62.1`
15
- const dartLocalSassModule = path.join(localSassModule, 'sass.dart.js'); // For `npm i -D sass <= 1.39.2`
12
+ const localSassModule = node.path.join(process.env.BALM_CWD, 'node_modules', 'sass');
13
+ let isLegacy = false;
14
+ try {
15
+ const sassPkg = requireModule(node.path.join(localSassModule, 'package.json'));
16
+ isLegacy = semver.lt(sassPkg.version, '1.40.0');
17
+ } catch (_) {}
18
+ const nodeLocalSassModule = node.path.join(localSassModule, 'sass.node.js');
19
+ const defaultLocalSassModule = node.path.join(localSassModule, 'sass.default.js'); // For `npm i -D sass <= 1.62.1`
20
+ const dartLocalSassModule = node.path.join(localSassModule, 'sass.dart.js'); // For `npm i -D sass <= 1.39.2`
16
21
  const sassModule = fs.existsSync(nodeLocalSassModule) ? requireModule(nodeLocalSassModule) : fs.existsSync(defaultLocalSassModule) ? requireModule(defaultLocalSassModule) : fs.existsSync(dartLocalSassModule) ? requireModule(dartLocalSassModule) : sass;
17
22
  const PLUGIN_NAME = 'sass';
18
23
  const transformObj = transform => new Transform({
@@ -23,7 +28,7 @@ const transformObj = transform => new Transform({
23
28
  /**
24
29
  * Handles returning the file to the stream
25
30
  */
26
- const filePush = (file, result, callback) => {
31
+ function filePush(file, result, callback) {
27
32
  // Build Source Maps!
28
33
  if (result.sourceMap) {
29
34
  const sassMap = result.sourceMap;
@@ -38,17 +43,59 @@ const filePush = (file, result, callback) => {
38
43
  file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
39
44
  }
40
45
  callback(null, file);
41
- };
46
+ }
47
+ function legacyFilePush(file, sassObject, callback) {
48
+ // Build Source Maps!
49
+ if (sassObject.map) {
50
+ // Transform map into JSON
51
+ const sassMap = JSON.parse(sassObject.map.toString());
52
+ // Grab the stdout and transform it into stdin
53
+ const sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
54
+ // Grab the base filename that's being worked on
55
+ const sassFileSrc = file.relative;
56
+ // Grab the path portion of the file that's being worked on
57
+ const sassFileSrcPath = node.path.dirname(sassFileSrc);
58
+ if (sassFileSrcPath) {
59
+ const sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
60
+ // Prepend the path to all files in the sources array except the file that's being worked on
61
+ sassMap.sources = sassMap.sources.map((source, index) => index === sourceFileIndex ? source : node.path.join(sassFileSrcPath, source));
62
+ }
63
+
64
+ // Remove 'stdin' from sources and replace with filenames!
65
+ sassMap.sources = sassMap.sources.filter(src => src !== 'stdin' && src);
66
+
67
+ // Replace the map file with the original filename (but new extension)
68
+ sassMap.file = replaceExtension(sassFileSrc, '.css');
69
+ // Apply the map
70
+ applySourceMap(file, sassMap);
71
+ }
72
+ file.contents = sassObject.css;
73
+ file.path = replaceExtension(file.path, '.css');
74
+ if (file.stat) {
75
+ file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
76
+ }
77
+ callback(null, file);
78
+ }
42
79
 
43
80
  /**
44
81
  * Handles error message
45
82
  */
46
- const handleError = (error, file, callback) => {
83
+ function handleError(error, file, callback) {
47
84
  const relativePath = node.path.relative(process.cwd(), file.path);
48
85
  const message = `${ansiColors.underline(relativePath)}\n${error.message}`;
49
86
  error.message = stripAnsi(message);
50
87
  return callback(new PluginError(PLUGIN_NAME, error));
51
- };
88
+ }
89
+ function legacyHandleError(error, file, callback) {
90
+ const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
91
+ const relativePath = node.path.relative(process.cwd(), filePath);
92
+ const message = `${ansiColors.underline(relativePath)}\n${error.formatted}`;
93
+ error.messageFormatted = message;
94
+ error.messageOriginal = error.message;
95
+ error.message = stripAnsi(message);
96
+ error.relativePath = relativePath;
97
+ return callback(new PluginError(PLUGIN_NAME, error));
98
+ }
52
99
 
53
100
  //////////////////////////////
54
101
  // Main Gulp Sass function
@@ -67,15 +114,41 @@ const gulpSass = options => transformObj((file, encoding, callback) => {
67
114
  file.path = replaceExtension(file.path, '.css');
68
115
  return callback(null, file);
69
116
  }
70
- const path = file.path;
117
+ const opts = options || {};
118
+ if (isLegacy) {
119
+ opts.data = file.contents.toString();
120
+
121
+ // We set the file path here so that libsass can correctly resolve import paths
122
+ opts.file = file.path;
123
+
124
+ // Ensure `indentedSyntax` is true if a `.sass` file
125
+ if (node.path.extname(file.path) === '.sass') {
126
+ opts.indentedSyntax = true;
127
+ }
71
128
 
72
- // Create alias
73
- if (!options.importers) {
74
- const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter(key => /^@[a-z0-9-]{1,213}/.test(key));
75
- if (aliasKeys.length) {
76
- const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
77
- options.importers = [{
78
- findFileUrl(url) {
129
+ // Ensure file's parent directory in the include path
130
+ if (opts.includePaths) {
131
+ if (typeof opts.includePaths === 'string') {
132
+ opts.includePaths = [opts.includePaths];
133
+ }
134
+ } else {
135
+ opts.includePaths = [];
136
+ }
137
+ opts.includePaths.unshift(node.path.dirname(file.path));
138
+
139
+ // Generate Source Maps if the source-map plugin is present
140
+ if (file.sourceMap) {
141
+ opts.sourceMap = file.path;
142
+ opts.omitSourceMapUrl = true;
143
+ opts.sourceMapContents = true;
144
+ }
145
+
146
+ // Create alias
147
+ if (!opts.importer) {
148
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter(key => /^@[a-z0-9-]{1,213}/.test(key));
149
+ if (aliasKeys.length) {
150
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
151
+ opts.importer = [function (url) {
79
152
  let file = url;
80
153
  const result = url.match(aliasKeyRegex);
81
154
  const key = result ? result[1] : null;
@@ -83,15 +156,38 @@ const gulpSass = options => transformObj((file, encoding, callback) => {
83
156
  file = url.replace(key, BalmJS.config.scripts.alias[key]);
84
157
  BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
85
158
  }
86
- return pathToFileURL(file);
87
- }
88
- }];
159
+ return {
160
+ file
161
+ };
162
+ }];
163
+ }
164
+ }
165
+ } else {
166
+ // Create alias
167
+ if (!options.importers) {
168
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter(key => /^@[a-z0-9-]{1,213}/.test(key));
169
+ if (aliasKeys.length) {
170
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
171
+ options.importers = [{
172
+ findFileUrl(url) {
173
+ let file = url;
174
+ const result = url.match(aliasKeyRegex);
175
+ const key = result ? result[1] : null;
176
+ if (key) {
177
+ file = url.replace(key, BalmJS.config.scripts.alias[key]);
178
+ BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
179
+ }
180
+ return pathToFileURL(file);
181
+ }
182
+ }];
183
+ }
89
184
  }
90
185
  }
91
186
  try {
92
- filePush(file, sassModule.compile(path, options), callback);
187
+ isLegacy ? legacyFilePush(file, sassModule.renderSync(opts), callback) : filePush(file, sassModule.compile(file.path, options), callback);
93
188
  } catch (error) {
94
- handleError(error, file, callback);
189
+ isLegacy ? legacyHandleError(error, file, callback) : handleError(error, file, callback);
95
190
  }
96
191
  });
97
- export default gulpSass;
192
+ export default gulpSass;
193
+ export { isLegacy };
@@ -1,11 +1,16 @@
1
+ import { isLegacy } from '../../plugins/sass.js';
1
2
  class SassTask extends BalmJS.BalmStyleTask {
2
3
  constructor() {
3
4
  super('sass');
4
5
  }
5
6
  get options() {
6
- return Object.assign({
7
+ return Object.assign(isLegacy ? {
8
+ includePaths: BalmJS.file.stylePaths,
9
+ outputStyle: 'expanded'
10
+ } : {
7
11
  loadPaths: BalmJS.file.stylePaths,
8
- sourceMap: true,
12
+ sourceMap: true
13
+ }, {
9
14
  quietDeps: BalmJS.config.logs.level < BalmJS.LogLevel.Warn
10
15
  }, BalmJS.config.styles.sassOptions, this.customOptions);
11
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "balm-core",
3
- "version": "4.26.0",
3
+ "version": "4.27.1",
4
4
  "description": "BalmJS compiler core",
5
5
  "keywords": [
6
6
  "balm",
@@ -48,13 +48,13 @@
48
48
  "babel-loader": "^9.1.3",
49
49
  "browser-sync": "^3.0.2",
50
50
  "connect-history-api-fallback": "^2.0.0",
51
- "css-loader": "^6.9.1",
51
+ "css-loader": "^6.10.0",
52
52
  "css-minimizer-webpack-plugin": "^6.0.0",
53
53
  "cssnano": "^6.0.3",
54
54
  "del": "^7.1.0",
55
- "dotenv": "^16.3.2",
55
+ "dotenv": "^16.4.1",
56
56
  "dotenv-expand": "^10.0.0",
57
- "esbuild": "^0.19.0",
57
+ "esbuild": "^0.20.0",
58
58
  "fancy-log": "^2.0.0",
59
59
  "gulp-eslint": "^6.0.0",
60
60
  "gulp-if": "^3.0.0",
@@ -72,22 +72,23 @@
72
72
  "imagemin": "^8.0.1",
73
73
  "istextorbinary": "^9.5.0",
74
74
  "less": "^4.2.0",
75
- "mini-css-extract-plugin": "^2.7.7",
75
+ "mini-css-extract-plugin": "^2.8.0",
76
76
  "modernizr": "^3.13.0",
77
77
  "parents": "^1.0.1",
78
78
  "plugin-error": "^2.0.1",
79
- "postcss": "^8.4.33",
79
+ "postcss": "^8.4.35",
80
80
  "postcss-flexbugs-fixes": "^5.0.2",
81
81
  "postcss-import": "^16.0.0",
82
82
  "postcss-load-config": "^5.0.2",
83
- "postcss-loader": "^8.0.0",
83
+ "postcss-loader": "^8.1.0",
84
84
  "postcss-preset-env": "7",
85
85
  "pretty-bytes": "^6.1.1",
86
86
  "readable-stream": "^4.5.2",
87
87
  "replace-ext": "^2.0.0",
88
88
  "rollup": "^4.9.6",
89
89
  "sass": "^1.70.0",
90
- "sass-loader": "^14.0.0",
90
+ "sass-loader": "^14.1.0",
91
+ "semver": "^7.6.0",
91
92
  "ssh2": "^1.15.0",
92
93
  "strip-ansi": "^7.1.0",
93
94
  "style-loader": "^3.3.4",
@@ -98,10 +99,10 @@
98
99
  "through2-concurrent": "^2.0.0",
99
100
  "tslib": "^2.6.2",
100
101
  "vinyl-sourcemaps-apply": "^0.2.1",
101
- "webpack": "^5.89.0",
102
+ "webpack": "^5.90.1",
102
103
  "webpack-bundle-analyzer": "^4.10.1",
103
104
  "webpack-dev-middleware": "^7.0.0",
104
- "webpack-hot-middleware": "^2.26.0",
105
+ "webpack-hot-middleware": "^2.26.1",
105
106
  "webpack-merge": "^5.10.0",
106
107
  "workbox-build": "^7.0.0"
107
108
  },
@@ -129,5 +130,5 @@
129
130
  "engines": {
130
131
  "node": ">=18.12.0"
131
132
  },
132
- "gitHead": "48763282dcc2f2c260fb9e606055e6eb89ff35c7"
133
+ "gitHead": "3b39b1c09422d96576573ea6423a732741f27653"
133
134
  }
@@ -1,17 +1,23 @@
1
- import path from 'node:path';
2
1
  import fs from 'node:fs';
3
2
  import { pathToFileURL } from 'node:url';
4
3
  import { Transform } from 'node:stream';
4
+ import semver from 'semver';
5
5
  import * as sass from 'sass';
6
6
  import replaceExtension from 'replace-ext';
7
7
  import stripAnsi from 'strip-ansi';
8
8
  import applySourceMap from 'vinyl-sourcemaps-apply';
9
9
  import ansiColors from 'ansi-colors';
10
10
  process.env.BALM_CWD = process.env.INIT_CWD || process.cwd();
11
- const localSassModule = path.join(process.env.BALM_ROOT || process.env.BALM_CWD, 'node_modules', 'sass');
12
- const nodeLocalSassModule = path.join(localSassModule, 'sass.node.js');
13
- const defaultLocalSassModule = path.join(localSassModule, 'sass.default.js');
14
- const dartLocalSassModule = path.join(localSassModule, 'sass.dart.js');
11
+ const localSassModule = node.path.join(process.env.BALM_CWD, 'node_modules', 'sass');
12
+ let isLegacy = false;
13
+ try {
14
+ const sassPkg = requireModule(node.path.join(localSassModule, 'package.json'));
15
+ isLegacy = semver.lt(sassPkg.version, '1.40.0');
16
+ }
17
+ catch (_) { }
18
+ const nodeLocalSassModule = node.path.join(localSassModule, 'sass.node.js');
19
+ const defaultLocalSassModule = node.path.join(localSassModule, 'sass.default.js');
20
+ const dartLocalSassModule = node.path.join(localSassModule, 'sass.dart.js');
15
21
  const sassModule = fs.existsSync(nodeLocalSassModule)
16
22
  ? requireModule(nodeLocalSassModule)
17
23
  : fs.existsSync(defaultLocalSassModule)
@@ -21,7 +27,7 @@ const sassModule = fs.existsSync(nodeLocalSassModule)
21
27
  : sass;
22
28
  const PLUGIN_NAME = 'sass';
23
29
  const transformObj = (transform) => new Transform({ transform, objectMode: true });
24
- const filePush = (file, result, callback) => {
30
+ function filePush(file, result, callback) {
25
31
  if (result.sourceMap) {
26
32
  const sassMap = result.sourceMap;
27
33
  sassMap.file = replaceExtension(file.relative, '.css');
@@ -33,13 +39,47 @@ const filePush = (file, result, callback) => {
33
39
  file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
34
40
  }
35
41
  callback(null, file);
36
- };
37
- const handleError = (error, file, callback) => {
42
+ }
43
+ function legacyFilePush(file, sassObject, callback) {
44
+ if (sassObject.map) {
45
+ const sassMap = JSON.parse(sassObject.map.toString());
46
+ const sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
47
+ const sassFileSrc = file.relative;
48
+ const sassFileSrcPath = node.path.dirname(sassFileSrc);
49
+ if (sassFileSrcPath) {
50
+ const sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
51
+ sassMap.sources = sassMap.sources.map((source, index) => index === sourceFileIndex
52
+ ? source
53
+ : node.path.join(sassFileSrcPath, source));
54
+ }
55
+ sassMap.sources = sassMap.sources.filter((src) => src !== 'stdin' && src);
56
+ sassMap.file = replaceExtension(sassFileSrc, '.css');
57
+ applySourceMap(file, sassMap);
58
+ }
59
+ file.contents = sassObject.css;
60
+ file.path = replaceExtension(file.path, '.css');
61
+ if (file.stat) {
62
+ file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
63
+ }
64
+ callback(null, file);
65
+ }
66
+ function handleError(error, file, callback) {
38
67
  const relativePath = node.path.relative(process.cwd(), file.path);
39
68
  const message = `${ansiColors.underline(relativePath)}\n${error.message}`;
40
69
  error.message = stripAnsi(message);
41
70
  return callback(new PluginError(PLUGIN_NAME, error));
42
- };
71
+ }
72
+ function legacyHandleError(error, file, callback) {
73
+ const filePath = ((error.file === 'stdin' ? file.path : error.file) ||
74
+ file.path);
75
+ const relativePath = node.path.relative(process.cwd(), filePath);
76
+ const message = `${ansiColors.underline(relativePath)}\n${error.formatted}`;
77
+ error.messageFormatted = message;
78
+ error.messageOriginal = error.message;
79
+ error.message = stripAnsi(message);
80
+ error.relativePath = relativePath;
81
+ return callback(new PluginError(PLUGIN_NAME, error));
82
+ }
43
83
  const gulpSass = (options) => transformObj((file, encoding, callback) => {
44
84
  if (file.isNull()) {
45
85
  return callback(null, file);
@@ -54,14 +94,33 @@ const gulpSass = (options) => transformObj((file, encoding, callback) => {
54
94
  file.path = replaceExtension(file.path, '.css');
55
95
  return callback(null, file);
56
96
  }
57
- const path = file.path;
58
- if (!options.importers) {
59
- const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter((key) => /^@[a-z0-9-]{1,213}/.test(key));
60
- if (aliasKeys.length) {
61
- const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
62
- options.importers = [
63
- {
64
- findFileUrl(url) {
97
+ const opts = (options || {});
98
+ if (isLegacy) {
99
+ opts.data = file.contents.toString();
100
+ opts.file = file.path;
101
+ if (node.path.extname(file.path) === '.sass') {
102
+ opts.indentedSyntax = true;
103
+ }
104
+ if (opts.includePaths) {
105
+ if (typeof opts.includePaths === 'string') {
106
+ opts.includePaths = [opts.includePaths];
107
+ }
108
+ }
109
+ else {
110
+ opts.includePaths = [];
111
+ }
112
+ opts.includePaths.unshift(node.path.dirname(file.path));
113
+ if (file.sourceMap) {
114
+ opts.sourceMap = file.path;
115
+ opts.omitSourceMapUrl = true;
116
+ opts.sourceMapContents = true;
117
+ }
118
+ if (!opts.importer) {
119
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter((key) => /^@[a-z0-9-]{1,213}/.test(key));
120
+ if (aliasKeys.length) {
121
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
122
+ opts.importer = [
123
+ function (url) {
65
124
  let file = url;
66
125
  const result = url.match(aliasKeyRegex);
67
126
  const key = result ? result[1] : null;
@@ -69,17 +128,44 @@ const gulpSass = (options) => transformObj((file, encoding, callback) => {
69
128
  file = url.replace(key, BalmJS.config.scripts.alias[key]);
70
129
  BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
71
130
  }
72
- return pathToFileURL(file);
131
+ return { file };
132
+ }
133
+ ];
134
+ }
135
+ }
136
+ }
137
+ else {
138
+ if (!options.importers) {
139
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter((key) => /^@[a-z0-9-]{1,213}/.test(key));
140
+ if (aliasKeys.length) {
141
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
142
+ options.importers = [
143
+ {
144
+ findFileUrl(url) {
145
+ let file = url;
146
+ const result = url.match(aliasKeyRegex);
147
+ const key = result ? result[1] : null;
148
+ if (key) {
149
+ file = url.replace(key, BalmJS.config.scripts.alias[key]);
150
+ BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
151
+ }
152
+ return pathToFileURL(file);
153
+ }
73
154
  }
74
- }
75
- ];
155
+ ];
156
+ }
76
157
  }
77
158
  }
78
159
  try {
79
- filePush(file, sassModule.compile(path, options), callback);
160
+ isLegacy
161
+ ? legacyFilePush(file, sassModule.renderSync(opts), callback)
162
+ : filePush(file, sassModule.compile(file.path, options), callback);
80
163
  }
81
164
  catch (error) {
82
- handleError(error, file, callback);
165
+ isLegacy
166
+ ? legacyHandleError(error, file, callback)
167
+ : handleError(error, file, callback);
83
168
  }
84
169
  });
85
170
  export default gulpSass;
171
+ export { isLegacy };
@@ -1,13 +1,18 @@
1
+ import { isLegacy } from '../../plugins/sass.js';
1
2
  class SassTask extends BalmJS.BalmStyleTask {
2
3
  constructor() {
3
4
  super('sass');
4
5
  }
5
6
  get options() {
6
- return Object.assign({
7
- loadPaths: BalmJS.file.stylePaths,
8
- sourceMap: true,
9
- quietDeps: BalmJS.config.logs.level < BalmJS.LogLevel.Warn
10
- }, BalmJS.config.styles.sassOptions, this.customOptions);
7
+ return Object.assign(isLegacy
8
+ ? {
9
+ includePaths: BalmJS.file.stylePaths,
10
+ outputStyle: 'expanded'
11
+ }
12
+ : {
13
+ loadPaths: BalmJS.file.stylePaths,
14
+ sourceMap: true
15
+ }, { quietDeps: BalmJS.config.logs.level < BalmJS.LogLevel.Warn }, BalmJS.config.styles.sassOptions, this.customOptions);
11
16
  }
12
17
  recipe(input, output, options = {}) {
13
18
  const balmSass = () => {