Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 625adc5

Browse files
committed
chore(sass): fix module builds
- fixes module builds broken by PR #12112 - break module imports out into a separate file since it behaves differently than Sass variables. - add a new `hoistScssAtUseStatements()` function to deduplicates @use statements and move them to the top as required by Sass. - start testing the module and closure builds for every PR and don't let breaking changes get to `master` before we find them. - update CircleCI NodeJS image and comments about where to find new images - update caniuse-lite
1 parent 4c935a3 commit 625adc5

File tree

7 files changed

+88
-19
lines changed

7 files changed

+88
-19
lines changed

.circleci/config.yml

+28-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# See http://blog.daemonl.com/2016/02/yaml.html
77
# To validate changes, use an online parser, eg. http://yaml-online-parser.appspot.com/
88

9-
# Find the latest version here: https://github.com/CircleCI-Public/circleci-dockerfiles/tree/master/node/images
9+
# Find the latest version and SHA here: https://hub.docker.com/r/circleci/node/tags
1010
var_1: &docker_image circleci/node:14.16.1-browsers
1111
var_2: &cache_key angularjs-material-{{ checksum "package-lock.json" }}
1212

@@ -44,7 +44,7 @@ var_7: &store_junit_test_results
4444
path: ./artifacts/junit
4545

4646
# Branch filter that we can specify for jobs that should only run on publish branches. This filter
47-
# is used to ensure that not all upstream branches will be published as Github builds
47+
# is used to ensure that not all upstream branches will be published as GitHub builds
4848
# (e.g. revert branches, feature branches)
4949
var_8: &publish_branches_filter
5050
branches:
@@ -104,6 +104,24 @@ jobs:
104104
- run: npm run build
105105
- *save_cache
106106

107+
build_js_modules:
108+
<<: *job_defaults
109+
steps:
110+
- checkout_and_rebase
111+
- *restore_cache
112+
- *npm_install
113+
- run: npm run build:modules
114+
- *save_cache
115+
116+
build_closure_modules:
117+
<<: *job_defaults
118+
steps:
119+
- checkout_and_rebase
120+
- *restore_cache
121+
- *npm_install
122+
- run: npm run build:closure
123+
- *save_cache
124+
107125
# ------------------------------------------------------------------------------------------
108126
# Jobs that run the unit tests on locally installed browsers (Chrome and Firefox headless).
109127
# The available browsers are included in the Docker image.
@@ -180,9 +198,17 @@ workflows:
180198
- test_angularjs_snapshot:
181199
requires:
182200
- build
201+
- build_js_modules:
202+
requires:
203+
- build
204+
- build_closure_modules:
205+
requires:
206+
- build
183207
- update_and_snapshot_docs:
184208
filters: *publish_branches_filter
185209
requires:
186210
- test_angularjs_1_7
187211
- test_angularjs_1_8
188212
- test_angularjs_snapshot
213+
- build_js_modules
214+
- build_closure_modules

gulp/config.js

+4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ module.exports = {
9494
'src/core/style/_mixins.scss'
9595
],
9696
themeCore: 'src/core/style/core-theme.scss',
97+
scssModules: 'src/core/style/_modules.scss',
9798
scssBaseFiles: [
99+
'src/core/style/_modules.scss',
98100
'src/core/style/_variables.scss',
99101
'src/components/input/_input-variables.scss',
100102
'src/core/style/_mixins.scss',
@@ -105,12 +107,14 @@ module.exports = {
105107
],
106108
scssServicesLayout: 'src/core/services/layout/layout.scss',
107109
scssLayoutFiles: [
110+
'src/core/style/_modules.scss',
108111
'src/core/style/_variables.scss',
109112
'src/core/style/_mixins.scss',
110113
'src/core/style/layout.scss',
111114
'src/core/services/layout/layout.scss'
112115
],
113116
scssLayoutAttributeFiles: [
117+
'src/core/style/_modules.scss',
114118
'src/core/style/_variables.scss',
115119
'src/core/style/_mixins.scss',
116120
'src/core/services/layout/layout-attributes.scss'

gulp/util.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,24 @@ function buildModule(module, opts) {
202202
return fs.readFileSync(fileName, 'utf8').toString();
203203
}).join('\n');
204204

205+
let sassModules;
206+
// Don't add the Sass modules to core since they get automatically included already.
207+
if (name === 'core') {
208+
sassModules = '';
209+
} else {
210+
sassModules = fs.readFileSync(config.scssModules, 'utf8').toString();
211+
}
212+
205213
return lazypipe()
206214
.pipe(insert.prepend, baseStyles)
207215
.pipe(gulpif, /theme.scss/, rename(name + '-default-theme.scss'), concat(name + '.scss'))
208216
// Theme files are suffixed with the `default-theme.scss` string.
209217
// In some cases there are multiple theme SCSS files, which should be concatenated together.
210218
.pipe(gulpif, /default-theme.scss/, concat(name + '-default-theme.scss'))
219+
// We can't prepend these earlier, or they get duplicated in a way that hoistScssAtUseStatements
220+
// can't deduplicate them.
221+
.pipe(insert.prepend, sassModules)
222+
.pipe(utils.hoistScssAtUseStatements)
211223
.pipe(sass)
212224
.pipe(dedupeCss)
213225
.pipe(utils.autoprefix)
@@ -246,7 +258,7 @@ function filterNonCodeFiles() {
246258
});
247259
}
248260

249-
// builds the theming related css and provides it as a JS const for angular
261+
// builds the theming related css and provides it as a JS const for AngularJS
250262
function themeBuildStream() {
251263
// Make a copy so that we don't modify the actual config that is used by other functions
252264
const paths = config.themeBaseFiles.slice(0);

package-lock.json

+3-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/gulp-utils.js

+39
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,45 @@ exports.hoistScssVariables = function() {
289289
});
290290
};
291291

292+
/**
293+
* Find Sass @use module imports and ensure that they are at the very top of the Sass prior to
294+
* running it through the Sass compiler. This also deduplicates @use statements to avoid errors.
295+
*/
296+
exports.hoistScssAtUseStatements = function() {
297+
return through2.obj(function(file, enc, next) {
298+
const contents = file.contents.toString().split('\n');
299+
let lastAtUseLineNumber = -1;
300+
const atUseStatements = [];
301+
302+
let openCount = 0;
303+
let closeCount = 0;
304+
let openBlock = false;
305+
306+
for (let currentLineNumber = 0; currentLineNumber < contents.length; ++currentLineNumber) {
307+
const line = contents[currentLineNumber];
308+
309+
if (openBlock || /^\s*@use\s/.test(line) && !/^\s+/.test(line)) {
310+
openCount += (line.match(/\(/g) || []).length;
311+
closeCount += (line.match(/\)/g) || []).length;
312+
openBlock = openCount !== closeCount;
313+
// Don't move statements from line 0 to line 0.
314+
if (currentLineNumber > 0) {
315+
const atUseStatement = contents.splice(currentLineNumber, 1)[0];
316+
// Don't write duplicate @use statements to avoid
317+
// 'There's already a module with namespace x' errors.
318+
if (!atUseStatements.includes(atUseStatement)) {
319+
atUseStatements.push(atUseStatement);
320+
contents.splice(++lastAtUseLineNumber, 0, atUseStatement);
321+
}
322+
}
323+
}
324+
}
325+
file.contents = Buffer.from(contents.join('\n'));
326+
this.push(file);
327+
next();
328+
});
329+
};
330+
292331
exports.cssToNgConstant = function(ngModule, factoryName) {
293332
return through2.obj(function(file, enc, next) {
294333

src/core/style/_modules.scss

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@use "sass:math";

src/core/style/_variables.scss

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
@use "sass:math";
21
// Typography
32
// ------------------------------
43
$font-family: Roboto, 'Helvetica Neue', sans-serif !default;

0 commit comments

Comments
 (0)