forked from bootstrap-vue/bootstrap-vue
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
185 lines (160 loc) · 6.12 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
const { resolve } = require('path')
// --- Constants ---
const RX_UN_KEBAB = /-(\w)/g
const RX_HYPHENATE = /\B([A-Z])/g
// Path to index file when using bootstrap-vue source code
const srcIndex = 'bootstrap-vue/src/index.js'
// --- Utility methods ---
// Converts PascalCase or camelCase to kebab-case
const kebabCase = str => {
return str.replace(RX_HYPHENATE, '-$1').toLowerCase()
}
// Converts a kebab-case or camelCase string to PascalCase
const pascalCase = str => {
str = kebabCase(str).replace(RX_UN_KEBAB, (_, c) => (c ? c.toUpperCase() : ''))
return str.charAt(0).toUpperCase() + str.slice(1)
}
const pickFirst = (...args) => {
for (const arg of args) {
if (arg !== undefined) {
return arg
}
}
}
// --- Main Nuxt.js module ---
module.exports = function nuxtBootstrapVue(moduleOptions = {}) {
this.nuxt.hook('build:before', () => {
// Merge moduleOptions with default
const options = {
...this.options.bootstrapVue,
...moduleOptions
}
// Ensure we have arrays
this.options.css = [].concat(this.options.css || [])
this.options.build.transpile = [].concat(this.options.build.transpile || [])
const bootstrapVueCSS = pickFirst(
options.bootstrapVueCSS,
options.bootstrapVueCss,
options.bvCSS,
// Defaults to `true` if no other options provided
true
)
if (bootstrapVueCSS) {
// Add BootstrapVue CSS
this.options.css.unshift('bootstrap-vue/dist/bootstrap-vue.css')
}
const bootstrapCSS = pickFirst(
options.bootstrapCSS,
options.bootstrapCss,
options.css,
// Defaults to `true` if no other options provided
true
)
if (bootstrapCSS) {
// Add Bootstrap CSS
this.options.css.unshift('bootstrap/dist/css/bootstrap.css')
}
// Component src prop resolving
this.options.build.loaders.vue.transformAssetUrls = {
// Nuxt default is missing `poster` for video
video: ['src', 'poster'],
// Nuxt default is missing image
image: 'xlink:href',
// Add BootstrapVue specific component asset items
'b-avatar': 'src',
'b-img': 'src',
'b-img-lazy': ['src', 'blank-src'],
'b-card': 'img-src',
'b-card-img': 'src',
'b-card-img-lazy': ['src', 'blank-src'],
'b-carousel-slide': 'img-src',
'b-embed': 'src',
// Ensure super supplied values/overrides are not lost
...this.options.build.loaders.vue.transformAssetUrls
}
// Enable transpilation of `src/` directory
this.options.build.transpile.push('bootstrap-vue/src')
// Use pre-transpiled or `src/`
const usePretranspiled = pickFirst(options.usePretranspiled, this.options.dev, false)
if (!usePretranspiled) {
// Use bootstrap-vue source code for smaller prod builds
// by aliasing 'bootstrap-vue' to the source files
this.extendBuild(config => {
if (!config.resolve.alias) {
config.resolve.alias = {}
}
const index = require.resolve(srcIndex)
const srcDir = index.replace(/index\.js$/, '')
// We prepend a $ to ensure that it is only used for
// `import from 'bootstrap-vue'` not `import from 'bootstrap-vue/*'`
config.resolve.alias['bootstrap-vue$'] = index
// If users are still cherry-picking modules from esm/ or es/ (legacy),
// alias them to src/ to prevent duplicate code imports
config.resolve.alias['bootstrap-vue/esm/'] = srcDir
config.resolve.alias['bootstrap-vue/es/'] = srcDir
})
}
// Base options available to template
const templateOptions = {
// Flag if we are tree shaking
treeShake: false,
icons: !!options.icons
}
// Specific component and/or directive plugins
for (const type of ['componentPlugins', 'directivePlugins']) {
const bvPlugins = Array.isArray(options[type]) ? options[type] : []
templateOptions[type] = bvPlugins
// Normalize plugin name to `${Name}Plugin` (component) or `VB${Name}Plugin` (directive)
// Required for backwards compatibility with old plugin import names
.map(plugin => {
// Ensure PascalCase name
plugin = pascalCase(plugin)
// Ensure new naming convention for directive plugins prefixed with `VB`
plugin = type === 'directivePlugins' && !/^VB/.test(plugin) ? `VB${plugin}` : plugin
// Ensure prefixed with `Plugin`
plugin = /Plugin$/.test(plugin) ? plugin : `${plugin}Plugin`
return plugin
})
// Remove duplicate items
.filter((plugin, i, arr) => arr.indexOf(plugin) === i)
if (templateOptions[type].length > 0) {
templateOptions.treeShake = true
}
}
// Specific components and/or directives
for (const type of ['components', 'directives']) {
const ComponentsOrDirectives = Array.isArray(options[type]) ? options[type] : []
templateOptions[type] = ComponentsOrDirectives
// Ensure PascalCase name
.map(item => pascalCase(item))
// Ensure prefixed with `V`
.map(item => (type === 'directives' && !/^V/.test(item) ? `V${item}` : item))
// Remove duplicate items
.filter((item, i, arr) => arr.indexOf(item) === i)
if (templateOptions[type].length > 0) {
templateOptions.treeShake = true
}
}
// If tree shaking, and icons requested, add in
// the IconsPlugin if not already specified
if (
templateOptions.treeShake &&
templateOptions.icons &&
templateOptions.componentPlugins.indexOf('IconsPlugin') === -1 &&
templateOptions.componentPlugins.indexOf('BootstrapVueIcons') === -1
) {
templateOptions.componentPlugins.push('IconsPlugin')
}
// Add BootstrapVue configuration if present
if (options.config && Object.prototype.toString.call(options.config) === '[object Object]') {
templateOptions.config = { ...options.config }
}
// Register plugin, passing options to plugin template
this.addPlugin({
src: resolve(__dirname, 'plugin.template.js'),
fileName: 'bootstrap-vue.js',
options: templateOptions
})
})
}
module.exports.meta = require('../package.json')