-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
276 lines (211 loc) · 8.42 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
'use strict';
// module requirements
const fs = require('fs');
const path = require('path');
const Funnel = require('broccoli-funnel');
const MergeTrees = require('broccoli-merge-trees');
module.exports = {
name: 'ember-cli-bootswatch',
defaultOptions: {
// theme: undefined, // REQUIRED option
importCSS: true,
importSass: false, // Auto-detect in `included()`
importJS: false, // || [array] of plugin names
importPopperJS: false // Auto-detect in `included()`
},
included(app) {
this._super.included.apply(this, arguments);
// Do not import anything if in "fastboot mode"
if ( process.env.EMBER_CLI_FASTBOOT ) {
return;
}
// Addon options from the apps ember-cli-build.js
let appOptions = (app.options && app.options[this.name]) || {};
// Options can just be a string of the theme,
// if so, convert to object and set the theme
if (typeof appOptions === 'string') {
appOptions = {'theme':appOptions};
}
// Bucket for auto-detected options
let detectedOptions = {};
// Detect if a bootstrap plugin depending on Popper.js will be imported
// http://getbootstrap.com/docs/4.0/getting-started/javascript/#dependencies
if ( appOptions.importJS === true || (typeof appOptions.importJS === 'array' && (
appOptions.importJS.includes('dropdown') ||
appOptions.importJS.includes('popover') ||
appOptions.importJS.includes('tooltip')
))) {
detectedOptions.importPopperJS = true;
}
// Detect if the consuming app has ember-cli-sass installed
if (app.dependencies().hasOwnProperty('ember-cli-sass')) {
detectedOptions.importCSS = false;
detectedOptions.importSass = true;
}
// Detect previous options and take those into account
// Note: These can be removed at some point down the road
let depreciatedOptions = {};
if (appOptions.excludeCSS) { // <= 2.0.0-beta.3
depreciatedOptions.importCSS = false;
this.ui.writeDeprecateLine(
`${this.name}: The option 'excludeCSS' has been replaced with 'importCSS'. ` +
'The previous option has been applied, but please update your options in "ember-cli-build.js".'
);
}
if (typeof appOptions.includeJSPlugins === 'array') { // 2.0.0-beta.1 through 2.0.0-beta.3
depreciatedOptions.importJS = appOptions.includeJSPlugins;
this.ui.writeDeprecateLine(
`${this.name}: The option 'includeJSPlugins' has been merged with 'importJS'. ` +
'The previous option has been applied, but please update your options in "ember-cli-build.js".'
);
}
if (appOptions.excludeJS) { // <= 2.0.0-beta.3
depreciatedOptions.importJS = false;
this.ui.writeDeprecateLine(
`${this.name}: The option 'excludeJS' has been replaced with 'importJS'. ` +
'The previous option has been applied, but please update your options in "ember-cli-build.js".'
);
}
if (appOptions.excludeFonts) { // <= 2.0.0-beta.3
this.ui.writeDeprecateLine(
`${this.name}: The option 'excludeFonts' has been removed because it does not apply to Bootstrap 4. ` +
'Please remove that option in your "ember-cli-build.js".'
);
}
// Combine all of the option sets,
// giving a proper priority order
let options = Object.assign(
{},
this.defaultOptions,
detectedOptions,
depreciatedOptions,
appOptions
);
// Set a default theme if none specified
if (!options.theme) {
options.theme = 'default';
this.ui.writeWarnLine(
`${this.name}: No theme specified, defaulting to the standard Bootstrap theme. ` +
`Define a "${this.name}":"theme-name" in your 'ember-cli-build.js' to get rid of this message.`
);
}
// Store final option set for use in 'treeForStyles()' below
this._options = options;
// Friendly message if the addon will not do anything
if (!options.importCSS && !options.importSass && !options.importJS && !options.importPopperJS) {
this.ui.writeError(
`${this.name}: All importing options are disabled (importCSS, importSass, importJS, importPopperJS). ` +
'This addon will not import anything into your build tree and effectively does nothing.'
);
}
// Import Bootswatch CSS and/or Sass
if (options.importCSS || options.importSass) {
// If not the "default" bootstrap theme,
// ensure the bootswatch theme exists
if (options.theme !== 'default') {
let bootswatchPath = path.dirname(
require.resolve('bootswatch/package.json')
);
let availableThemes = fs.readdirSync(
path.join( bootswatchPath, 'dist' )
);
// Fail if theme does not exist
if (!availableThemes.includes(options.theme)) {
throw new Error(
`${this.name}: Theme (${options.theme}) is not available, ` +
`not listed as an option from bootswatch; default, ${availableThemes.join(', ')}.`
);
}
} // if (options.theme !== 'default')
// Determine the theme CSS path
let themePath = (
options.theme === 'default' ?
path.join('node_modules', 'bootstrap', 'dist', 'css') :
path.join('node_modules', 'bootswatch', 'dist', options.theme)
);
// Import Bootswatch CSS
if (options.importCSS) {
this.import(
path.join(themePath, 'bootstrap.css')
);
}
// Import Bootswatch Sass
if (options.importSass) {
// Nothing to do here, treeForStyles() below will handle the rest
}
} // if (options.importCSS)
// Import the Popper.js dependency
// Note, should probably come before imported bootstrap plugins
if (options.importPopperJS) {
this.import(
path.join('node_modules', 'popper.js', 'dist', 'umd', 'popper.js')
);
}
// Import Bootstrap JS
if (options.importJS) {
if (typeof options.importJS === 'array') {
// Get all available plugins
let bootstrapPath = path.dirname(
require.resolve('bootstrap/package.json')
);
let pluginFiles = fs.readdirSync(
path.join( bootstrapPath, 'js', 'dist' )
);
let availablePlugins = pluginFiles.map(function( file ){
return file.split('.')[0]; // remove extensions
}).reduce(function( files, file ){
if ( !files.includes(file) ) files.push(file);
return files; // return a unique list
}, []);
let unavailablePlugins = [];
// Attempt to import each plugin
for (let pluginName of options.importJS) {
if (availablePlugins.includes(pluginName)) {
this.import(
path.join('node_modules', 'bootstrap', 'js', 'dist', pluginName + '.js')
);
} else {
unavailablePlugins.push(pluginName);
}
}
// Fail if any plugins are unavailable
if (unavailablePlugins.length > 0) {
throw new Error(
`${this.name}: Some 'importJS' plugins are not available (${unavailablePlugins.join(', ')}), ` +
`not listed as an option from bootstrap; ${availablePlugins.join(', ')}.`
);
}
} else { // import all bootstrap plugins
this.import(
path.join('node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.js')
);
} // if (typeof options.importJS === 'array')
} // if (options.importJS)
}, // included()
treeForStyles(/* tree */) {
let superTree = this._super.treeForStyles.apply(this, arguments);
// Do not continue if *.scss files are not needed
if (!this._options.importSass) {
return superTree;
}
let bootstrapPath = path.dirname(
require.resolve('bootstrap/package.json')
);
let bootstrapTree = Funnel(
path.join(bootstrapPath, 'scss'),
{ include: ['**/*.scss'], destDir: `${this.name}/bootstrap` }
);
// 'default' theme only uses bootstrap, no need for bootswatch (next)
if (this._options.theme === 'default') {
return MergeTrees([superTree, bootstrapTree]);
}
let bootswatchPath = path.dirname(
require.resolve('bootswatch/package.json')
);
let bootswatchTree = Funnel(
path.join(bootswatchPath, 'dist', this._options.theme),
{ include: ['**/*.scss'], destDir: `${this.name}/bootswatch` }
);
return MergeTrees([superTree, bootstrapTree, bootswatchTree]);
} // treeForStyles()
}; // module.exports