Skip to content

Commit

Permalink
feat: add stylus preprocessor support (#120)
Browse files Browse the repository at this point in the history
* Implemented stylus preprocessor support
* Added stylus to dependencies in package.json 
* Added tests for relative resolves for stylus and included paths for node_modules
  • Loading branch information
alexkpek authored and dherges committed Sep 12, 2017
1 parent ee9499e commit 19933cd
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 163 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ We keep track of user questions in GitHub's issue tracker and try to build a doc
- :sparkles: CSS Features
- :camel: Runs [SCSS](http://sass-lang.com/guide) preprocessor, supporting the [relative `~` import syntax](https://github.com/webpack-contrib/sass-loader#imports)
- :elephant: Runs [less](http://lesscss.org/#getting-started) preprocessor
- :snake: Runs [Stylus](http://stylus-lang.com) preprocessor, resolves relative paths relative to ng-package.json
- :monkey: Adds vendor-specific prefixes w/ [autoprefixer](https://github.com/postcss/autoprefixer#autoprefixer-) and [browserslist](https://github.com/ai/browserslist#queries) — just tell your desired `.browserslistrc`


Expand Down
28 changes: 28 additions & 0 deletions integration/samples/custom/specs/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ describe(`sample-custom`, () => {
expect(baz.styles[0]).to.not.contain(`@red: #ff0000`);
});

describe(`stylus styles`, () => {
it(`should contain rendered styles`, () => {
const fooBar = METADATA['metadata']['FooBarComponent']['decorators'][0]['arguments'][0];

expect(fooBar).to.be.ok;
expect(fooBar.styles[0]).to.contain(`color: #f00;`);
expect(fooBar.styles[0]).to.not.contain(`color: $color`);
});

it(`should contain imported styles`, () => {
const fooBar = METADATA['metadata']['FooBarComponent']['decorators'][0]['arguments'][0];

expect(fooBar).to.be.ok;
expect(fooBar.styles[0]).to.contain(`background-color: #008000;`);
expect(fooBar.styles[0]).to.not.contain(`background-color: $color-green;`);
});

it(`should contain imported image path`, () => {
const fooBar = METADATA['metadata']['FooBarComponent']['decorators'][0]['arguments'][0];

expect(fooBar).to.be.ok;
expect(fooBar.styles[0]).to.contain(`background-image: url("../styles/assets/test.png");`);
expect(fooBar.styles[0]).to.not.contain(`background-color: url(./assets/test.png);`);
});
});



it(`should re-export 'InternalService' with an auto-generated symbol`, () => {
expect(METADATA['metadata']['ɵa']).to.be.ok;
expect(METADATA['origins']['ɵa']).to.equal('./internal.service');
Expand Down
5 changes: 3 additions & 2 deletions integration/samples/custom/src/custom.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { CommonModule } from '@angular/common';
import { FooComponent } from './foo/foo.component';
import { BarComponent } from './bar/bar.component';
import { BazComponent } from './baz/baz.component';
import { FooBarComponent } from './foo-bar/foo-bar.component';
import { InternalService } from './internal.service';

@NgModule({
imports[ CommonModule ],
declarations: [ FooComponent, BarComponent, BazComponent ],
exports: [ FooComponent, BarComponent, BazComponent ]
declarations: [ FooComponent, BarComponent, BazComponent, FooBarComponent ],
exports: [ FooComponent, BarComponent, BazComponent, FooBarComponent ]
})
export class CustomModule {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Foo-Bar!</h1>
8 changes: 8 additions & 0 deletions integration/samples/custom/src/foo-bar/foo-bar.component.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@import "../styles/variables.styl"
$color = red

h1
color $color
background-color $color-green
background-image $image

8 changes: 8 additions & 0 deletions integration/samples/custom/src/foo-bar/foo-bar.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Component } from '@angular/core';

@Component({
selector: 'sample-foo-bar',
templateUrl: './foo-bar.component.html',
styleUrls: ['./foo-bar.component.styl']
})
export class FooBarComponent {}
1 change: 1 addition & 0 deletions integration/samples/custom/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './foo/foo.component';
export * from './bar/bar.component';
export * from './baz/baz.component';
export * from './foo-bar/foo-bar.component';
export * from './custom.module';
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions integration/samples/custom/src/styles/variables.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$color-green = green;
$image = url(./assets/test.png);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"rollup": "^0.49.0",
"rollup-plugin-node-resolve": "^3.0.0",
"sorcery": "^0.10.0",
"stylus": "^0.54.5",
"ts-node": "^3.0.4",
"typescript": "^2.3.2",
"uglify-js": "^3.0.7",
Expand Down
37 changes: 35 additions & 2 deletions src/lib/steps/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const browserslist = require('browserslist');
import postcss = require('postcss');
const sass = require('node-sass');
import * as less from 'less';
import * as stylus from 'stylus';


/**
Expand All @@ -36,7 +37,7 @@ export const processAssets = (src: string, dest: string): Promise<any> => {
styleProcessor: (path, ext, file, cb) => {

debug(`render stylesheet ${path}`);
const render = pickRenderer(path, ext, file);
const render = pickRenderer(path, ext, file, src);

debug(`postcss with autoprefixer for ${path}`);
const browsers = browserslist(undefined, { path });
Expand Down Expand Up @@ -77,7 +78,7 @@ const sassImporter = (url: string): any => {
}


const pickRenderer = (filePath: string, ext: string[], file: string): Promise<string> => {
const pickRenderer = (filePath: string, ext: string[], file: string, srcPath: string): Promise<string> => {

switch (path.extname(filePath)) {

Expand All @@ -90,6 +91,11 @@ const pickRenderer = (filePath: string, ext: string[], file: string): Promise<st
debug(`rendering less for ${filePath}`);
return renderLess({ filename: filePath });

case '.styl':
case '.stylus':
debug(`rendering styl for ${filePath}`);
return renderStylus({ filename: filePath, root: srcPath });

case '.css':
default:
return Promise.resolve(file);
Expand Down Expand Up @@ -125,3 +131,30 @@ const renderLess = (lessOpts: any): Promise<string> => {
})
}));
}

/**
* filename - absolute path to file
* root - root folder of project (where ng-package.json is located)
*/
const renderStylus = ({ filename, root }): Promise<string> => {
return readFile(filename)
.then((stylusData: string) => new Promise<string>((resolve, reject) => {
stylus(stylusData)
// add paths for resolve
.include(root)
.include('.')
// add support for resolving plugins from node_modules
.include('node_modules')
.set('filename', filename)
// turn on url resolver in stylus, same as flag --resolve-url
.set('resolve url', true)
.define('url', stylus.resolver())
.render((err, css) => {
if (err) {
reject(err);
} else {
resolve(css);
}
});
}));
}
Loading

0 comments on commit 19933cd

Please sign in to comment.