Skip to content

Commit 9cddafd

Browse files
committed
chore(sass): Added Support for Less to Sass Conversion
1 parent a50b9be commit 9cddafd

File tree

6 files changed

+1227
-1701
lines changed

6 files changed

+1227
-1701
lines changed

Gruntfile.js

Lines changed: 158 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ module.exports = function (grunt) {
55

66
function init () {
77

8+
// '--sass' command line argument exists?
9+
var sassBuild = grunt.option('sass');
10+
811
grunt.initConfig({
912
availabletasks: {
1013
tasks: {
@@ -94,6 +97,17 @@ module.exports = function (grunt) {
9497
dest: 'dist/less/dependencies/patternfly',
9598
expand: true,
9699
flatten: true
100+
},
101+
sassBuild:{
102+
files: [
103+
{
104+
// copy css built from sass into dist/styles
105+
expand: true,
106+
cwd: 'dist/sass',
107+
src: ['**/*.css', '**/*.map'],
108+
dest: 'dist/styles/'
109+
}
110+
]
97111
}
98112
},
99113
'string-replace': {
@@ -115,6 +129,127 @@ module.exports = function (grunt) {
115129
}
116130
}
117131
},
132+
lessToSass: {
133+
convert_within_custom_replacements: {
134+
files: [
135+
{
136+
expand: true,
137+
cwd: 'styles',
138+
src: ['**/*.less', '!angular-patternfly.less'],
139+
dest: 'dist/sass/',
140+
rename: function(dest, src) {
141+
return dest + '_' + src.replace('.less', '.scss');
142+
}
143+
},
144+
{
145+
expand: true,
146+
cwd: 'src',
147+
src: ['**/*.less'],
148+
dest: 'dist/sass/',
149+
rename: function(dest, src) {
150+
return dest + '_' + src.replace('.less', '.scss');
151+
}
152+
}
153+
],
154+
options: {
155+
excludes: ['variables', 'default'],
156+
replacements: [
157+
{
158+
// Customize variable conversion to include newer css reserved words.
159+
pattern: /(?!@debug|@import|@media|@keyframes|@font-face|@include|@extend|@mixin|@supports|@-\w)@/gi,
160+
replacement: '$',
161+
order: 0
162+
},
163+
{
164+
// Add !default flag to variable declarations without leading whitespace.
165+
pattern: /^(\$.*?:.*?);(\s*\/\/.*)?$/mgi,
166+
replacement: '$1 !default;$2',
167+
order: 2
168+
},
169+
{
170+
// Include mixins with no arguments
171+
pattern: /(\s+)\.([\w\-]+)\(\)/gi,
172+
replacement: '$1@include $2()',
173+
order: 3
174+
},
175+
{
176+
// Interpolates second ampersand where double ampersands are used
177+
pattern: /\&\&/gi,
178+
replacement: '&#{&}',
179+
order: 20
180+
},
181+
{
182+
// Interpolates ampersands that directly follow (are touching) a definition
183+
// e.g. somedef& becomes somedef#{&}
184+
pattern: /(\w+)\&/gi,
185+
replacement: '$1#{&}',
186+
order: 30
187+
},
188+
{
189+
// Namespaced mixins are detected as includes by default conversion
190+
// process. Remove namespacing by concatenating namespace and mixin name.
191+
// #gradient {
192+
// @include striped(){...}
193+
// }
194+
//
195+
// becomes
196+
//
197+
// @mixin gradient-striped(){...}
198+
pattern: /^#([\w\-]+)\s*{\s*@include\s*([\w\-]*)\((.*)\)\s*{([\s\S]*?)}\s*}/mgi,
199+
replacement: '@mixin $1-$2($3){$4}',
200+
order: 40
201+
},
202+
// Fix invocation of namespaced mixins. Replace #namespace > .mixin()
203+
// or #namespace.mixin() with @include namespace-mixin()
204+
{
205+
pattern: /#(\w*)\s*\>?\s*\.(\w*)(\(.*\))/gi,
206+
replacement: '@include $1-$2$3',
207+
order: 50
208+
},
209+
{
210+
// Remove "!default" flag from mixin declarations
211+
pattern: /@mixin.*!default.*/gi,
212+
replacement: function(match) {
213+
return match.replace(/\s*!default\s*/gi, '');
214+
},
215+
order: 60
216+
},
217+
{
218+
// Replace semi-colons with commas in mixins and includes
219+
pattern: /(@mixin |@include )([\w\-]*)\s*(\(.*\))(\s*[{;]?)/gi,
220+
replacement: function(match, p1, p2, p3, p4) {
221+
return p1 + p2 + p3.replace(/;/g, ',') + p4;
222+
},
223+
order: 70
224+
},
225+
{
226+
// Fix bug in grunt-less-to-sass that puts "!important" inside mixin and css function parens.
227+
pattern: /^(\s*[\w\-]*:\s*[\w\-]*)\((.*?)\s*!important.*\)(.*);(.*)$/mgi,
228+
replacement: '$1($2) !important$3;$4',
229+
order: 80
230+
},
231+
{
232+
pattern: /\&:extend\((.*)\)/gi,
233+
replacement: '@extend $1',
234+
order: 90
235+
},
236+
]
237+
}
238+
}
239+
},
240+
sass: {
241+
patternfly: {
242+
files: {
243+
'dist/sass/angular-patternfly.css': ['styles/build.scss']
244+
},
245+
options: {
246+
outputStyle: 'expanded',
247+
includePaths: [
248+
'node_modules/patternfly/dist/sass/patternfly/'
249+
]
250+
}
251+
}
252+
},
118253
less: {
119254
patternfly: {
120255
files: {
@@ -355,6 +490,12 @@ module.exports = function (grunt) {
355490
}
356491
});
357492

493+
grunt.registerTask('shipcss', function() {
494+
if (sassBuild) {
495+
grunt.task.run('copy:sassBuild');
496+
}
497+
});
498+
358499
grunt.registerTask('copymain', ['copy:docdata', 'copy:fa', 'copy:img', 'copy:distimg', 'copy:distless', 'copy:distlessDependencies']);
359500

360501
// You can specify which modules to build as arguments of the build task.
@@ -375,7 +516,23 @@ module.exports = function (grunt) {
375516
concatSrc = 'src/**/*.js';
376517
}
377518

378-
grunt.task.run(['clean', 'lint', 'test', 'ngtemplates', 'concat', 'ngAnnotate', 'uglify:build', 'less', 'cssmin', 'copymain', 'string-replace', 'ngdocs', 'clean:templates']);
519+
grunt.task.run([
520+
'clean',
521+
'lint',
522+
'test',
523+
'ngtemplates',
524+
'concat',
525+
'ngAnnotate',
526+
'uglify:build',
527+
'less',
528+
'lessToSass',
529+
'sass',
530+
'shipcss',
531+
'cssmin',
532+
'copymain',
533+
'string-replace',
534+
'ngdocs',
535+
'clean:templates']);
379536
});
380537

381538
// Runs all the tasks of build with the exception of tests

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,22 @@ Note:
194194
</style>
195195
```
196196
197+
#### Less to Sass Conversion
198+
199+
During the build process Less files are converted to Sass files in `/dist/sass`. Then the Sass files are compiled into `/dist/sass/angular-patternfly.css`. If you would like to copy the Sass generated css into the main `/dist/styles` directory, execute:
200+
201+
```
202+
grunt build --sass
203+
```
204+
205+
This task will copy `/dist/sass/angular-patternfly.css` to `/dist/styles/angular-patternfly.css`. Then the build process will minimize the css in `/dist/styles`.
206+
207+
The Less to Sass Conversion step will be accomplished and managed as a part of any Pull Request which includes Less file changes. Although contributors may want to build and test their style changes with Sass before submitting a Pull Request, this step should always be tested and validated by reviewers before a style change is merged and released. If a contributor is having issues with Sass conversion that they cannot resolve, Pull Request reviewers will need to ensure that the Sass conversion step is successfully accomplished, tested, and included in the Pull Request before it is approved and merged.
208+
209+
For more detailed information, please read [PatternFly Less to Sass Conversion](https://github.com/patternfly/patternfly#less-to-sass-conversion)
210+
211+
*Note:* When a Less file is added/deleted/renamed it needs to be updated in the main Less import file `/styles/angular-patternfly.less` and the main Sass import file `/styles/build.scss`.
212+
197213
### Using with Webpack
198214
199215
In order to use Angular-Patternfly in a Webpack-bundled application there are some things you need to keep in mind:

eslint.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ globals:
1111
rules:
1212
strict: [2, "function"]
1313
quotes: 0
14-
camelcase: 2
14+
camelcase: 1
1515
indent: [2, 2]
1616
new-cap:
1717
- 2

0 commit comments

Comments
 (0)