From 9ab85c0eaefb017e08f78f6171a321d45a8f1e3f Mon Sep 17 00:00:00 2001 From: Jonas Metzener Date: Thu, 30 Nov 2017 14:15:07 +0100 Subject: [PATCH 1/4] Add possibility to exclude certain parts from the build --- app/styles/ember-uikit.scss | 6 +- index.js | 126 +++++++++++++++++++++++++++++--- tests/dummy/app/styles/app.scss | 2 +- 3 files changed, 119 insertions(+), 15 deletions(-) diff --git a/app/styles/ember-uikit.scss b/app/styles/ember-uikit.scss index 036cf4c9..75ce67cd 100644 --- a/app/styles/ember-uikit.scss +++ b/app/styles/ember-uikit.scss @@ -1,3 +1,3 @@ -@import 'uikit/src/scss/variables-theme'; -@import 'uikit/src/scss/mixins-theme'; -@import 'uikit/src/scss/uikit-theme'; \ No newline at end of file +@import 'ember-uikit/variables-theme'; +@import 'ember-uikit/mixins-theme'; +@import 'ember-uikit/uikit-theme'; diff --git a/index.js b/index.js index 304b7d84..cb4f2fb6 100644 --- a/index.js +++ b/index.js @@ -3,28 +3,132 @@ const Funnel = require('broccoli-funnel'); const Merge = require('broccoli-merge-trees'); +const path = require('path'); + +const DEFAULT_OPTIONS = { + importUIkitCSS: true, + importUIkitJS: true, + importUIkitIcons: true, + importUIkitAssets: true, + + useIcons: true +}; + +// For ember-cli < 2.7 findHost doesnt exist so we backport from that version +// for earlier version of ember-cli. +// https://github.com/ember-cli/ember-cli/blame/16e4492c9ebf3348eb0f31df17215810674dbdf6/lib/models/addon.js#L533 module.exports = { name: 'ember-uikit', + findHost() { + let fn = + this._findHost || + function() { + let current = this; + let app; + do { + app = current.app || app; + } while (current.parent.parent && (current = current.parent)); + return app; + }; + + return fn.call(this); + }, + treeForPublic(tree) { - let uikitImages = new Funnel('node_modules/uikit/src/images', { - destDir: '/assets/images/' - }); + let uikitAssets = + this.uikitOptions.importUIkitAssets && + Funnel(this._getAssetsPath(), { + destDir: '/assets/images/components' + }); - return new Merge([uikitImages, tree].filter(Boolean)); + let uikitIcons = + this.uikitOptions.useIcons && + this.uikitOptions.importUIkitIcons && + new Funnel(this._getIconsPath(), { + destDir: '/assets/images/icons' + }); + + return new Merge([uikitAssets, uikitIcons, tree].filter(Boolean)); + }, + + treeForStyles(tree) { + let uikitStyles = + this._hasSass() && + this.uikitOptions.importUIkitCSS && + new Funnel(this._getStylesPath(), { + destDir: 'ember-uikit' + }); + + return new Merge([uikitStyles, tree].filter(Boolean)); }, - included(app) { + included() { this._super.included.apply(this, arguments); - app.options.sassOptions = app.options.sassOptions || {}; - app.options.sassOptions.includePaths = - app.options.sassOptions.includePaths || []; + this.app = this.findHost(); + + let options = Object.assign( + Object.assign({}, DEFAULT_OPTIONS), + this.app.options['ember-uikit'] + ); + + this.uikitOptions = options; + + if (!this._hasSass() && this.uikitOptions.importUIkitCSS) { + // use compiled css version of uikit + this.app.import(path.join(this._getStylesPath(), 'uikit.css')); + } + + if (this.uikitOptions.importUIkitJS) { + this.app.import(path.join(this._getDistPath(), 'js', 'uikit.js')); + + if (this.uikitOptions.useIcons) { + this.app.import(path.join(this._getDistPath(), 'js', 'uikit-icons.js')); + } + } + }, + + _hasSass() { + return !!this.app.project.findAddonByName('ember-cli-sass'); + }, + + _getNodeModulesPath() { + return path.relative(process.cwd(), this.app.project.nodeModulesPath); + }, + + _getDistPath() { + return path.join(this._getNodeModulesPath(), 'uikit', 'dist'); + }, + + _getIconsPath() { + return path.join( + this._getNodeModulesPath(), + 'uikit', + 'src', + 'images', + 'icons' + ); + }, + + _getAssetsPath() { + return path.join( + this._getNodeModulesPath(), + 'uikit', + 'src', + 'images', + 'components' + ); + }, + + _getStylesPath() { + let uikitPath = path.join(this._getNodeModulesPath(), 'uikit'); - app.options.sassOptions.includePaths.push('node_modules'); + if (this._hasSass()) { + return path.join(uikitPath, 'src', 'scss'); + } - app.import('node_modules/uikit/dist/js/uikit.js'); - app.import('node_modules/uikit/dist/js/uikit-icons.js'); + return path.join(uikitPath, 'dist', 'css'); } }; diff --git a/tests/dummy/app/styles/app.scss b/tests/dummy/app/styles/app.scss index 201da6eb..e0703e73 100644 --- a/tests/dummy/app/styles/app.scss +++ b/tests/dummy/app/styles/app.scss @@ -26,4 +26,4 @@ $base-heading-font-weight: 300; left: 0; top: 50%; transform: translateX(calc(-100% - 5px)); -} \ No newline at end of file +} From 89ef48ff119d04c1c6e3ad826a9fa606163eed22 Mon Sep 17 00:00:00 2001 From: Jonas Metzener Date: Tue, 5 Dec 2017 10:47:43 +0100 Subject: [PATCH 2/4] Add white- and blacklist and add uk-icon to blacklist if useIcons: false --- index.js | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index cb4f2fb6..5637ba6a 100644 --- a/index.js +++ b/index.js @@ -11,16 +11,24 @@ const DEFAULT_OPTIONS = { importUIkitIcons: true, importUIkitAssets: true, - useIcons: true + useIcons: true, + + whitelist: [], + blacklist: [] }; -// For ember-cli < 2.7 findHost doesnt exist so we backport from that version -// for earlier version of ember-cli. -// https://github.com/ember-cli/ember-cli/blame/16e4492c9ebf3348eb0f31df17215810674dbdf6/lib/models/addon.js#L533 +const componentDependencies = { + 'uk-switcher': ['uk-tab', 'uk-subnav'] +}; module.exports = { name: 'ember-uikit', + /** + * For ember-cli < 2.7 findHost doesnt exist so we backport from that version + * for earlier version of ember-cli. + * https://github.com/ember-cli/ember-cli/blame/16e4492c9ebf3348eb0f31df17215810674dbdf6/lib/models/addon.js#L533 + */ findHost() { let fn = this._findHost || @@ -76,6 +84,10 @@ module.exports = { this.uikitOptions = options; + if (!this.uikitOptions.useIcons) { + this.uikitOptions.blacklist.push('uk-icon'); + } + if (!this._hasSass() && this.uikitOptions.importUIkitCSS) { // use compiled css version of uikit this.app.import(path.join(this._getStylesPath(), 'uikit.css')); @@ -90,6 +102,85 @@ module.exports = { } }, + _generateWhitelist(whitelist) { + let list = []; + + if (!whitelist) { + return list; + } + + function _addToWhitelist(item) { + if (list.indexOf(item) === -1) { + list.push(item); + + if (componentDependencies[item]) { + componentDependencies[item].forEach(_addToWhitelist); + } + } + } + + whitelist.forEach(_addToWhitelist); + return list; + }, + + treeForAddon(tree) { + return this._super.treeForAddon.call(this, this._filterComponents(tree)); + }, + + treeForAddonTemplates(tree) { + return this._super.treeForAddonTemplates.call( + this, + this._filterComponents(tree) + ); + }, + + /** + * Treeshaking stolen from ember-bootstrap all credits to @kaliber5 + */ + _filterComponents(tree) { + let whitelist = this._generateWhitelist(this.uikitOptions.whitelist); + let blacklist = this.uikitOptions.blacklist || []; + + // exit early if no opts defined + if (whitelist.length === 0 && blacklist.length === 0) { + return tree; + } + + return new Funnel(tree, { + exclude: [name => this._excludeComponent(name, whitelist, blacklist)] + }); + }, + + _excludeComponent(name, whitelist, blacklist) { + let regex = /^(templates\/)?components\//; + let isComponent = regex.test(name); + + if (!isComponent) { + return false; + } + + let baseName = name.replace(regex, ''); + let firstSeparator = baseName.indexOf('/'); + if (firstSeparator !== -1) { + baseName = baseName.substring(0, firstSeparator); + } else { + baseName = baseName.substring(0, baseName.lastIndexOf('.')); + } + + let isWhitelisted = whitelist.indexOf(baseName) !== -1; + let isBlacklisted = blacklist.indexOf(baseName) !== -1; + + if (whitelist.length === 0 && blacklist.length === 0) { + return false; + } + + if (whitelist.length && blacklist.length === 0) { + return !isWhitelisted; + } + + return isBlacklisted; + }, + _hasSass() { return !!this.app.project.findAddonByName('ember-cli-sass'); }, From 4badb1cac12334a485964ab1cc02429d6d060fdf Mon Sep 17 00:00:00 2001 From: Jonas Metzener Date: Tue, 5 Dec 2017 11:03:45 +0100 Subject: [PATCH 3/4] Add documentation for build options --- tests/dummy/app/snippets/.eslintrc.js | 3 + tests/dummy/app/snippets/configuration.js | 12 ++++ tests/dummy/app/templates/index.hbs | 70 +++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 tests/dummy/app/snippets/.eslintrc.js create mode 100644 tests/dummy/app/snippets/configuration.js diff --git a/tests/dummy/app/snippets/.eslintrc.js b/tests/dummy/app/snippets/.eslintrc.js new file mode 100644 index 00000000..79ab432f --- /dev/null +++ b/tests/dummy/app/snippets/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + rules: { 'no-undef': 'off' } +}; diff --git a/tests/dummy/app/snippets/configuration.js b/tests/dummy/app/snippets/configuration.js new file mode 100644 index 00000000..b87662c8 --- /dev/null +++ b/tests/dummy/app/snippets/configuration.js @@ -0,0 +1,12 @@ +// ember-cli-build.js + +module.exports = function(defaults) { + let app = new EmberApp(defaults, { + 'ember-uikit': { + useIcons: false, + whitelist: ['uk-button', 'uk-card'] + } + }); + + return app.toTree(); +}; diff --git a/tests/dummy/app/templates/index.hbs b/tests/dummy/app/templates/index.hbs index 14d3b1d6..cc484894 100644 --- a/tests/dummy/app/templates/index.hbs +++ b/tests/dummy/app/templates/index.hbs @@ -22,6 +22,76 @@ include to app/styles/app.scss.

+

Configuration

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
importUIkitCSSBooleanfalseWhether to import the CSS of UIkit
importUIkitJSBooleanfalseWhether to import the JS of UIkit
importUIkitAssetsBooleanfalseWhether to import the assets of UIkit
importUIkitIconsBooleanfalseWhether to import the icons of UIkit
useIconsBooleantrueWhether to use UIkits icons
whitelistString[][] + A list of included components. Only components in this list will be + included in your build. You should never use whitelist + and blacklist! +
blacklistString[][] + A list of excluded components. Only components not in this list will + be included in your build +
+ +

+ Those options can be configured in your ember-cli-build.js file: +

+ +{{code-snippet name='configuration.js'}} +

Contribution

From a539fa1c1d825f6c2aeeff3280d5737d0f6a93f3 Mon Sep 17 00:00:00 2001 From: Jonas Metzener Date: Tue, 5 Dec 2017 16:06:10 +0100 Subject: [PATCH 4/4] Consistent naming --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 5637ba6a..13f12892 100644 --- a/index.js +++ b/index.js @@ -17,7 +17,7 @@ const DEFAULT_OPTIONS = { blacklist: [] }; -const componentDependencies = { +const COMPONENT_DEPENDENCIES = { 'uk-switcher': ['uk-tab', 'uk-subnav'] }; @@ -113,8 +113,8 @@ module.exports = { if (list.indexOf(item) === -1) { list.push(item); - if (componentDependencies[item]) { - componentDependencies[item].forEach(_addToWhitelist); + if (COMPONENT_DEPENDENCIES[item]) { + COMPONENT_DEPENDENCIES[item].forEach(_addToWhitelist); } } }