balm-core 4.26.0 → 4.27.0

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,20 @@
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';
6
- import * as sass from 'sass';
5
+ import semver from 'semver';
6
+ import 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
+ const sassPkg = requireModule(node.path.join(localSassModule, 'package.json'));
14
+ export const isLegacy = semver.lt(sassPkg.version, '1.40.0');
15
+ const nodeLocalSassModule = node.path.join(localSassModule, 'sass.node.js');
16
+ const defaultLocalSassModule = node.path.join(localSassModule, 'sass.default.js'); // For `npm i -D sass <= 1.62.1`
17
+ const dartLocalSassModule = node.path.join(localSassModule, 'sass.dart.js'); // For `npm i -D sass <= 1.39.2`
16
18
  const sassModule = fs.existsSync(nodeLocalSassModule) ? requireModule(nodeLocalSassModule) : fs.existsSync(defaultLocalSassModule) ? requireModule(defaultLocalSassModule) : fs.existsSync(dartLocalSassModule) ? requireModule(dartLocalSassModule) : sass;
17
19
  const PLUGIN_NAME = 'sass';
18
20
  const transformObj = transform => new Transform({
@@ -23,7 +25,7 @@ const transformObj = transform => new Transform({
23
25
  /**
24
26
  * Handles returning the file to the stream
25
27
  */
26
- const filePush = (file, result, callback) => {
28
+ function filePush(file, result, callback) {
27
29
  // Build Source Maps!
28
30
  if (result.sourceMap) {
29
31
  const sassMap = result.sourceMap;
@@ -38,17 +40,59 @@ const filePush = (file, result, callback) => {
38
40
  file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
39
41
  }
40
42
  callback(null, file);
41
- };
43
+ }
44
+ function legacyFilePush(file, sassObject, callback) {
45
+ // Build Source Maps!
46
+ if (sassObject.map) {
47
+ // Transform map into JSON
48
+ const sassMap = JSON.parse(sassObject.map.toString());
49
+ // Grab the stdout and transform it into stdin
50
+ const sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
51
+ // Grab the base filename that's being worked on
52
+ const sassFileSrc = file.relative;
53
+ // Grab the path portion of the file that's being worked on
54
+ const sassFileSrcPath = node.path.dirname(sassFileSrc);
55
+ if (sassFileSrcPath) {
56
+ const sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
57
+ // Prepend the path to all files in the sources array except the file that's being worked on
58
+ sassMap.sources = sassMap.sources.map((source, index) => index === sourceFileIndex ? source : node.path.join(sassFileSrcPath, source));
59
+ }
60
+
61
+ // Remove 'stdin' from sources and replace with filenames!
62
+ sassMap.sources = sassMap.sources.filter(src => src !== 'stdin' && src);
63
+
64
+ // Replace the map file with the original filename (but new extension)
65
+ sassMap.file = replaceExtension(sassFileSrc, '.css');
66
+ // Apply the map
67
+ applySourceMap(file, sassMap);
68
+ }
69
+ file.contents = sassObject.css;
70
+ file.path = replaceExtension(file.path, '.css');
71
+ if (file.stat) {
72
+ file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
73
+ }
74
+ callback(null, file);
75
+ }
42
76
 
43
77
  /**
44
78
  * Handles error message
45
79
  */
46
- const handleError = (error, file, callback) => {
80
+ function handleError(error, file, callback) {
47
81
  const relativePath = node.path.relative(process.cwd(), file.path);
48
82
  const message = `${ansiColors.underline(relativePath)}\n${error.message}`;
49
83
  error.message = stripAnsi(message);
50
84
  return callback(new PluginError(PLUGIN_NAME, error));
51
- };
85
+ }
86
+ function legacyHandleError(error, file, callback) {
87
+ const filePath = (error.file === 'stdin' ? file.path : error.file) || file.path;
88
+ const relativePath = node.path.relative(process.cwd(), filePath);
89
+ const message = `${ansiColors.underline(relativePath)}\n${error.formatted}`;
90
+ error.messageFormatted = message;
91
+ error.messageOriginal = error.message;
92
+ error.message = stripAnsi(message);
93
+ error.relativePath = relativePath;
94
+ return callback(new PluginError(PLUGIN_NAME, error));
95
+ }
52
96
 
53
97
  //////////////////////////////
54
98
  // Main Gulp Sass function
@@ -67,15 +111,41 @@ const gulpSass = options => transformObj((file, encoding, callback) => {
67
111
  file.path = replaceExtension(file.path, '.css');
68
112
  return callback(null, file);
69
113
  }
70
- const path = file.path;
114
+ const opts = options || {};
115
+ if (isLegacy) {
116
+ opts.data = file.contents.toString();
117
+
118
+ // We set the file path here so that libsass can correctly resolve import paths
119
+ opts.file = file.path;
120
+
121
+ // Ensure `indentedSyntax` is true if a `.sass` file
122
+ if (node.path.extname(file.path) === '.sass') {
123
+ opts.indentedSyntax = true;
124
+ }
71
125
 
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) {
126
+ // Ensure file's parent directory in the include path
127
+ if (opts.includePaths) {
128
+ if (typeof opts.includePaths === 'string') {
129
+ opts.includePaths = [opts.includePaths];
130
+ }
131
+ } else {
132
+ opts.includePaths = [];
133
+ }
134
+ opts.includePaths.unshift(node.path.dirname(file.path));
135
+
136
+ // Generate Source Maps if the source-map plugin is present
137
+ if (file.sourceMap) {
138
+ opts.sourceMap = file.path;
139
+ opts.omitSourceMapUrl = true;
140
+ opts.sourceMapContents = true;
141
+ }
142
+
143
+ // Create alias
144
+ if (!opts.importer) {
145
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter(key => /^@[a-z0-9-]{1,213}/.test(key));
146
+ if (aliasKeys.length) {
147
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
148
+ opts.importer = [function (url) {
79
149
  let file = url;
80
150
  const result = url.match(aliasKeyRegex);
81
151
  const key = result ? result[1] : null;
@@ -83,15 +153,37 @@ const gulpSass = options => transformObj((file, encoding, callback) => {
83
153
  file = url.replace(key, BalmJS.config.scripts.alias[key]);
84
154
  BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
85
155
  }
86
- return pathToFileURL(file);
87
- }
88
- }];
156
+ return {
157
+ file
158
+ };
159
+ }];
160
+ }
161
+ }
162
+ } else {
163
+ // Create alias
164
+ if (!options.importers) {
165
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter(key => /^@[a-z0-9-]{1,213}/.test(key));
166
+ if (aliasKeys.length) {
167
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
168
+ options.importers = [{
169
+ findFileUrl(url) {
170
+ let file = url;
171
+ const result = url.match(aliasKeyRegex);
172
+ const key = result ? result[1] : null;
173
+ if (key) {
174
+ file = url.replace(key, BalmJS.config.scripts.alias[key]);
175
+ BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
176
+ }
177
+ return pathToFileURL(file);
178
+ }
179
+ }];
180
+ }
89
181
  }
90
182
  }
91
183
  try {
92
- filePush(file, sassModule.compile(path, options), callback);
184
+ isLegacy ? legacyFilePush(file, sassModule.renderSync(opts), callback) : filePush(file, sassModule.compile(file.path, options), callback);
93
185
  } catch (error) {
94
- handleError(error, file, callback);
186
+ isLegacy ? legacyHandleError(error, file, callback) : handleError(error, file, callback);
95
187
  }
96
188
  });
97
189
  export default gulpSass;
@@ -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.0",
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": "795dbf08a8fca7ea10f5e38f9c658d53f0a3ca5e"
133
134
  }
@@ -1,17 +1,19 @@
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';
5
- import * as sass from 'sass';
4
+ import semver from 'semver';
5
+ import 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
+ const sassPkg = requireModule(node.path.join(localSassModule, 'package.json'));
13
+ export const isLegacy = semver.lt(sassPkg.version, '1.40.0');
14
+ const nodeLocalSassModule = node.path.join(localSassModule, 'sass.node.js');
15
+ const defaultLocalSassModule = node.path.join(localSassModule, 'sass.default.js');
16
+ const dartLocalSassModule = node.path.join(localSassModule, 'sass.dart.js');
15
17
  const sassModule = fs.existsSync(nodeLocalSassModule)
16
18
  ? requireModule(nodeLocalSassModule)
17
19
  : fs.existsSync(defaultLocalSassModule)
@@ -21,7 +23,7 @@ const sassModule = fs.existsSync(nodeLocalSassModule)
21
23
  : sass;
22
24
  const PLUGIN_NAME = 'sass';
23
25
  const transformObj = (transform) => new Transform({ transform, objectMode: true });
24
- const filePush = (file, result, callback) => {
26
+ function filePush(file, result, callback) {
25
27
  if (result.sourceMap) {
26
28
  const sassMap = result.sourceMap;
27
29
  sassMap.file = replaceExtension(file.relative, '.css');
@@ -33,13 +35,47 @@ const filePush = (file, result, callback) => {
33
35
  file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
34
36
  }
35
37
  callback(null, file);
36
- };
37
- const handleError = (error, file, callback) => {
38
+ }
39
+ function legacyFilePush(file, sassObject, callback) {
40
+ if (sassObject.map) {
41
+ const sassMap = JSON.parse(sassObject.map.toString());
42
+ const sassMapFile = sassMap.file.replace(/^stdout$/, 'stdin');
43
+ const sassFileSrc = file.relative;
44
+ const sassFileSrcPath = node.path.dirname(sassFileSrc);
45
+ if (sassFileSrcPath) {
46
+ const sourceFileIndex = sassMap.sources.indexOf(sassMapFile);
47
+ sassMap.sources = sassMap.sources.map((source, index) => index === sourceFileIndex
48
+ ? source
49
+ : node.path.join(sassFileSrcPath, source));
50
+ }
51
+ sassMap.sources = sassMap.sources.filter((src) => src !== 'stdin' && src);
52
+ sassMap.file = replaceExtension(sassFileSrc, '.css');
53
+ applySourceMap(file, sassMap);
54
+ }
55
+ file.contents = sassObject.css;
56
+ file.path = replaceExtension(file.path, '.css');
57
+ if (file.stat) {
58
+ file.stat.atime = file.stat.mtime = file.stat.ctime = new Date();
59
+ }
60
+ callback(null, file);
61
+ }
62
+ function handleError(error, file, callback) {
38
63
  const relativePath = node.path.relative(process.cwd(), file.path);
39
64
  const message = `${ansiColors.underline(relativePath)}\n${error.message}`;
40
65
  error.message = stripAnsi(message);
41
66
  return callback(new PluginError(PLUGIN_NAME, error));
42
- };
67
+ }
68
+ function legacyHandleError(error, file, callback) {
69
+ const filePath = ((error.file === 'stdin' ? file.path : error.file) ||
70
+ file.path);
71
+ const relativePath = node.path.relative(process.cwd(), filePath);
72
+ const message = `${ansiColors.underline(relativePath)}\n${error.formatted}`;
73
+ error.messageFormatted = message;
74
+ error.messageOriginal = error.message;
75
+ error.message = stripAnsi(message);
76
+ error.relativePath = relativePath;
77
+ return callback(new PluginError(PLUGIN_NAME, error));
78
+ }
43
79
  const gulpSass = (options) => transformObj((file, encoding, callback) => {
44
80
  if (file.isNull()) {
45
81
  return callback(null, file);
@@ -54,14 +90,33 @@ const gulpSass = (options) => transformObj((file, encoding, callback) => {
54
90
  file.path = replaceExtension(file.path, '.css');
55
91
  return callback(null, file);
56
92
  }
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) {
93
+ const opts = (options || {});
94
+ if (isLegacy) {
95
+ opts.data = file.contents.toString();
96
+ opts.file = file.path;
97
+ if (node.path.extname(file.path) === '.sass') {
98
+ opts.indentedSyntax = true;
99
+ }
100
+ if (opts.includePaths) {
101
+ if (typeof opts.includePaths === 'string') {
102
+ opts.includePaths = [opts.includePaths];
103
+ }
104
+ }
105
+ else {
106
+ opts.includePaths = [];
107
+ }
108
+ opts.includePaths.unshift(node.path.dirname(file.path));
109
+ if (file.sourceMap) {
110
+ opts.sourceMap = file.path;
111
+ opts.omitSourceMapUrl = true;
112
+ opts.sourceMapContents = true;
113
+ }
114
+ if (!opts.importer) {
115
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter((key) => /^@[a-z0-9-]{1,213}/.test(key));
116
+ if (aliasKeys.length) {
117
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
118
+ opts.importer = [
119
+ function (url) {
65
120
  let file = url;
66
121
  const result = url.match(aliasKeyRegex);
67
122
  const key = result ? result[1] : null;
@@ -69,17 +124,43 @@ const gulpSass = (options) => transformObj((file, encoding, callback) => {
69
124
  file = url.replace(key, BalmJS.config.scripts.alias[key]);
70
125
  BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
71
126
  }
72
- return pathToFileURL(file);
127
+ return { file };
128
+ }
129
+ ];
130
+ }
131
+ }
132
+ }
133
+ else {
134
+ if (!options.importers) {
135
+ const aliasKeys = Object.keys(BalmJS.config.scripts.alias).filter((key) => /^@[a-z0-9-]{1,213}/.test(key));
136
+ if (aliasKeys.length) {
137
+ const aliasKeyRegex = new RegExp(`^(${aliasKeys.join('|')})/`);
138
+ options.importers = [
139
+ {
140
+ findFileUrl(url) {
141
+ let file = url;
142
+ const result = url.match(aliasKeyRegex);
143
+ const key = result ? result[1] : null;
144
+ if (key) {
145
+ file = url.replace(key, BalmJS.config.scripts.alias[key]);
146
+ BalmJS.logger.debug(`${PLUGIN_NAME} alias`, `${key} -> ${url} => ${file}`);
147
+ }
148
+ return pathToFileURL(file);
149
+ }
73
150
  }
74
- }
75
- ];
151
+ ];
152
+ }
76
153
  }
77
154
  }
78
155
  try {
79
- filePush(file, sassModule.compile(path, options), callback);
156
+ isLegacy
157
+ ? legacyFilePush(file, sassModule.renderSync(opts), callback)
158
+ : filePush(file, sassModule.compile(file.path, options), callback);
80
159
  }
81
160
  catch (error) {
82
- handleError(error, file, callback);
161
+ isLegacy
162
+ ? legacyHandleError(error, file, callback)
163
+ : handleError(error, file, callback);
83
164
  }
84
165
  });
85
166
  export default gulpSass;
@@ -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 = () => {