Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

feat(sass): added compatibility for sass #40

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Allows to use Web Components using ES6 modules in an Ember application.

## Installation

```
```bash
ember install ember-cli-webcomponents-bundler
```

Expand Down Expand Up @@ -46,50 +46,50 @@ import './components/some-component/some-component';
import './components/another-component/another-component';
```

**Output**
## Output

A bundled file will be generated for each of the `entrypointPaths` in the directory with the name of the entry point path. For example, the bundle for `lib/path-one` will be saved in `dist/assets/path-one/bundle.js`.
A bundled file will be generated for each of the `entrypointPaths` in the directory with the name of the entry point path. For example, the bundle for `lib/path-one` will be saved in `dist/assets/path-one/bundle.js`.

Both, the bundle name and the output path can be configured by setting them as `outputFileName` and `outputPath` respectively.

## Options

### `entrypointFileName`

type: `String`
type: `String`
default: `module-imports.js`

Name of the file used as entry point for ES modules inside each entry point path.

### `outputFileName`

type: `String`
type: `String`
default: `bundle.js`

Name of the generated bundle for each entry point path.

### `outputPath`

type: `String`
type: `String`
default: `assets`

Path where the generated bundle will be saved inside the dist folder.

### `minify`

type: `Boolean`
type: `Boolean`
default: `false` (`true` in production env)

Minifies the bundle.

### `modules`

type: `Boolean`
default: `false`
type: `Boolean`
default: `false`

Generates two bundles: one for browsers with ES6 modules support and another for the rest of browsers using the build presets of the app.targets.

### `entrypointPaths`
### `entrypointPaths`

type: `Array`
default: `[]`
Expand All @@ -98,19 +98,33 @@ List of paths where the addon will search for an entry point to generate its cor

### `autoImport`

type: `Boolean`
default: `true`
type: `Boolean`
default: `true`

Writes the script tags for the bundle(s) in index.html. You can disable this option if you want to import the scripts on demand.
Writes the script tags for the bundle(s) in index.html. You can disable this option if you want to import the scripts on demand.

When this option is set to `false`, [webcomponents.js polyfill](https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs) is not included in `vendor.js`, so you must import it explicitly before the bundle.

### `importStyles`

type: `Boolean`
type: `Boolean`
default: `false`

Allows to import css files in components.
Allows to import css and scss files in components. For sass compiler we use [node-sass](https://sass-lang.com/documentation/js-api).

### `sassTemplate``

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of declare 2 properties to pass the templates, I think it would be easies to define a map where the key is the file extension and the value is the template path:

styleTemplates: {
    css: '......',
    sass: '......'
}

This simplifies your code when retrieving the path and prevent using a lot of arguments if you add support for more templates:

this._getTreeWithImportedStyles(dirname, this.config.styleTemplates)

// ...

const template = await readFile(styleTemplates[fileExtension], 'utf8');;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one. I have implemented your recommendation. Check it out!


type: `String`
default: `./lib/templates/base_css_template.tmpl``

Use an specific template to the scss->css->css-in-js translation. You can add imports or specific js code that you need this way without further modification.

### `cssTemplate``

type: `String`
default: `./lib/templates/base_css_template.tmpl``

Use an specific template to the css->css-in-js translation. You can add imports or specific js code that you need this way without further modification.

Example:

Expand All @@ -122,7 +136,7 @@ The imported files exports the styles in a template literal that can be interpol

### `dedupe`

type: `Array`
type: `Array`
default: `[]`

Module names that should be resolved from the app `node_modules` instead of another packages requiring them. Helps to prevent bundling the same package multiple times if package is imported from dependencies.
Expand All @@ -143,17 +157,14 @@ Example:

If you want to contribute to this addon, please read the [CONTRIBUTING.md](CONTRIBUTING.md).


## Versioning

We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/BBVAEngineering/ember-cli-webcomponents-bundler/tags).


## Authors

See the list of [contributors](https://github.com/BBVAEngineering/ember-cli-webcomponents-bundler/graphs/contributors) who participated in this project.


## License

This project is licensed under the [MIT License](LICENSE.md).
18 changes: 12 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const rollupConfig = require('./lib/config/rollup');
const outputConfig = require('./lib/config/output');
const BroccoliStyleExport = require('./lib/broccoli-style-export');
const path = require('path');
const extend = require('deep-extend');

module.exports = {
name: require('./package').name,
Expand Down Expand Up @@ -36,10 +37,14 @@ module.exports = {
entrypointPaths: [],
autoImport: true,
importStyles: false,
styleTemplates: {
sass: './lib/templates/base_css_template.tmpl',
css: './lib/templates/base_css_template.tmpl',
},
dedupe: []
};

this.options = Object.assign(defaults, options);
this.options = extend(defaults, options);
this.options.rootURL = url;

this._setOutputOptions();
Expand Down Expand Up @@ -103,26 +108,27 @@ module.exports = {
return `${root}${this.options.outputPath}/${dirname}/${filename}${ext}`;
},

_getTreeWithImportedStyles(inputNode) {
_getTreeWithImportedStyles(inputNode, styleTemplates) {
const { browsers } = this.app.project.targets;
const styleScripts = new BroccoliStyleExport(inputNode, {
autoprefixer: {
overrideBrowserslist: browsers
}
},
styleTemplates
});

return funnel(styleScripts, { exclude: ['**/*.css'] });
return funnel(styleScripts, { exclude: ['**/*.css', '**/*.scss'] });
},

postprocessTree(type, tree) {
if (type !== 'all') {
return tree;
}

const { importStyles } = this.options;
const { importStyles, styleTemplates } = this.options;
const rollupTrees = this.options.entrypointPaths.map((dirname) => {
const absEntrypointPath = path.join(this.app.project.root, dirname);
const rollupInput = importStyles ? this._getTreeWithImportedStyles(dirname) : absEntrypointPath;
const rollupInput = importStyles ? this._getTreeWithImportedStyles(dirname, styleTemplates) : absEntrypointPath;
const basename = path.basename(dirname, this.options.entrypointFileName); // last part of the path
const getOutputFileName = (config) => this._getOutputFilePath(basename, true, config.name === 'modules');

Expand Down
40 changes: 31 additions & 9 deletions lib/broccoli-style-export.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,66 @@
/* eslint-disable no-sync */
/* eslint-env node */

'use strict';

const fs = require('fs-extra');
const Filter = require('broccoli-persistent-filter');
const extend = require('deep-extend');
const path = require('path');
const sass = require('node-sass');
const postcss = require('postcss');
const styleprefixer = require('autoprefixer');

const EXTENSION_TO_TEMPLATES = {
scss: 'sass',
sass: 'sass',
css: 'css'
};

class BroccoliStyleExport extends Filter {
constructor(inputNodes, options) {
super(inputNodes, {
annotation: 'BroccoliStyleProcessor'
});

const defaults = {
extensions: ['css'],
targetExtension: 'css.js',
autoprefixer: {}
extensions: ['sass', 'scss', 'css'],
autoprefixer: {},
useLitHtml: false
};

this.options = extend(defaults, options);
this.options.template = 'export default`{{styles}}`;';
}

getDestFilePath(relativePath) {
const { ext } = path.parse(relativePath);
const { extensions, targetExtension } = this.options;
const { extensions } = this.options;
const fileExtension = ext.slice(1);

if (extensions.includes(fileExtension)) {
return relativePath.replace(fileExtension, targetExtension);
return relativePath.replace(fileExtension, `${fileExtension}.js`);
}

return null;
}

async processString(content) {
const { autoprefixer, template } = this.options;
const { css } = await postcss(styleprefixer(autoprefixer)).process(content, {
async processString(content, relativePath) {
const { ext } = path.parse(relativePath);
const fileExtension = ext.slice(1);
const { autoprefixer, styleTemplates } = this.options;

let digested = content;

if (fileExtension === 'scss') {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think of adding broccoli-persistent-filter to speed-up the build. This is a simple step, you only have to wrap your tree inside other tree.

digested = sass.renderSync({
data: digested,
outputStyle: 'compressed'
}).css;
}

const template = await fs.readFile(styleTemplates[EXTENSION_TO_TEMPLATES[fileExtension]], 'utf8');

const { css } = await postcss(styleprefixer(autoprefixer)).process(digested, {
from: undefined, to: undefined
});

Expand Down
5 changes: 5 additions & 0 deletions lib/config/rollup.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ module.exports = function({
return;
}

/* istanbul ignore if */
if (warning.code === 'CIRCULAR_DEPENDENCY') {
return;
}

next(warning);
};

Expand Down
1 change: 1 addition & 0 deletions lib/templates/base_css_template.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default`{{styles}}`;
Loading