@stackline/angular-multiselect-dropdown 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +264 -0
- package/angular2-multiselect-dropdown.ts +1 -0
- package/gulpfile.js +68 -0
- package/inline-resources.js +119 -0
- package/multiselect.component.css +618 -0
- package/multiselect.component.css.map +1 -0
- package/npm-debug.log.3264368948 +0 -0
- package/package.json +118 -0
- package/src/app/angular2-multiselect-dropdown/angular2-multiselect-dropdown.ts +6 -0
- package/src/app/angular2-multiselect-dropdown/clickOutside.ts +60 -0
- package/src/app/angular2-multiselect-dropdown/index.ts +6 -0
- package/src/app/angular2-multiselect-dropdown/list-filter.ts +29 -0
- package/src/app/angular2-multiselect-dropdown/menu-item.ts +55 -0
- package/src/app/angular2-multiselect-dropdown/multiselect.component.html +88 -0
- package/src/app/angular2-multiselect-dropdown/multiselect.component.scss +593 -0
- package/src/app/angular2-multiselect-dropdown/multiselect.component.ts +381 -0
- package/src/app/angular2-multiselect-dropdown/multiselect.interface.ts +21 -0
- package/src/app/angular2-multiselect-dropdown/multiselect.model.ts +13 -0
- package/tsconfig-aot.json +32 -0
- package/tsconfig.json +36 -0
- package/webpack-test.config.ts +70 -0
- package/webpack-umd.config.ts +98 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright (c) 2016 Cuppa Labs
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
|
12
|
+
all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# @stackline/angular-multiselect-dropdown
|
|
2
|
+
|
|
3
|
+
Angular 2 multiselect dropdown component for web applications. Easy to integrate and use.
|
|
4
|
+
|
|
5
|
+
## Compatibility
|
|
6
|
+
|
|
7
|
+
This package version is compatible with Angular 2.x and was tested in a real Angular 2.4.10 application.
|
|
8
|
+
|
|
9
|
+
- Package: `@stackline/angular-multiselect-dropdown@2.0.3`
|
|
10
|
+
- Angular peer range: `>=2.0.0 <3.0.0`
|
|
11
|
+
- Tested Angular runtime: `2.4.10`
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
##### 1. Getting Started
|
|
15
|
+
##### 2. Installation
|
|
16
|
+
##### 3. Usage
|
|
17
|
+
##### 4. Templates
|
|
18
|
+
##### 5. Template Driven Forms support
|
|
19
|
+
##### 5. Reactive Forms support
|
|
20
|
+
##### 6. Settings configuration
|
|
21
|
+
##### 7. Callbacks and events
|
|
22
|
+
##### 8. Lazy lodaing - handle large data lists
|
|
23
|
+
##### 9. Group By feature
|
|
24
|
+
##### 10. Search filter for both plain list and grouped list
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Getting Started
|
|
31
|
+
### Installation
|
|
32
|
+
- The Mutiselect Dropdown package is published as `@stackline/angular-multiselect-dropdown`.
|
|
33
|
+
- Install the tested Angular 2 package:
|
|
34
|
+
`npm install @stackline/angular-multiselect-dropdown@2.0.3`
|
|
35
|
+
|
|
36
|
+
- Once installed import `AngularMultiSelectModule` from the installed package into your module as follows:
|
|
37
|
+
|
|
38
|
+
### Theme option
|
|
39
|
+
|
|
40
|
+
The package ships two built-in skins:
|
|
41
|
+
|
|
42
|
+
- `classic` keeps the original compact layout and is the default.
|
|
43
|
+
- `material` enables the rounded chip and list-item spacing skin.
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
this.dropdownSettings = {
|
|
47
|
+
text: 'Select Countries',
|
|
48
|
+
enableSearchFilter: true,
|
|
49
|
+
theme: 'material'
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Usage
|
|
54
|
+
Import `AngularMultiSelectModule` into `NgModule` in `app.module.ts`
|
|
55
|
+
```js
|
|
56
|
+
import { AngularMultiSelectModule } from '@stackline/angular-multiselect-dropdown/angular2-multiselect-dropdown';
|
|
57
|
+
|
|
58
|
+
@NgModule({
|
|
59
|
+
// ...
|
|
60
|
+
imports: [
|
|
61
|
+
AngularMultiSelectModule,
|
|
62
|
+
]
|
|
63
|
+
// ...
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Declare the component data variables and options in your component where you want to consume the dropdown component.
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
|
|
72
|
+
import { Component, OnInit } from '@angular/core';
|
|
73
|
+
|
|
74
|
+
export class AppComponent implements OnInit {
|
|
75
|
+
dropdownList = [];
|
|
76
|
+
selectedItems = [];
|
|
77
|
+
dropdownSettings = {};
|
|
78
|
+
ngOnInit(){
|
|
79
|
+
this.dropdownList = [
|
|
80
|
+
{"id":1,"itemName":"India"},
|
|
81
|
+
{"id":2,"itemName":"Singapore"},
|
|
82
|
+
{"id":3,"itemName":"Australia"},
|
|
83
|
+
{"id":4,"itemName":"Canada"},
|
|
84
|
+
{"id":5,"itemName":"South Korea"},
|
|
85
|
+
{"id":6,"itemName":"Germany"},
|
|
86
|
+
{"id":7,"itemName":"France"},
|
|
87
|
+
{"id":8,"itemName":"Russia"},
|
|
88
|
+
{"id":9,"itemName":"Italy"},
|
|
89
|
+
{"id":10,"itemName":"Sweden"}
|
|
90
|
+
];
|
|
91
|
+
this.selectedItems = [
|
|
92
|
+
{"id":2,"itemName":"Singapore"},
|
|
93
|
+
{"id":3,"itemName":"Australia"},
|
|
94
|
+
{"id":4,"itemName":"Canada"},
|
|
95
|
+
{"id":5,"itemName":"South Korea"}
|
|
96
|
+
];
|
|
97
|
+
this.dropdownSettings = {
|
|
98
|
+
singleSelection: false,
|
|
99
|
+
text:"Select Countries",
|
|
100
|
+
selectAllText:'Select All',
|
|
101
|
+
unSelectAllText:'UnSelect All',
|
|
102
|
+
enableSearchFilter: true,
|
|
103
|
+
classes:"myclass custom-class"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
onItemSelect(item:any){
|
|
107
|
+
console.log(item);
|
|
108
|
+
console.log(this.selectedItems);
|
|
109
|
+
}
|
|
110
|
+
OnItemDeSelect(item:any){
|
|
111
|
+
console.log(item);
|
|
112
|
+
console.log(this.selectedItems);
|
|
113
|
+
}
|
|
114
|
+
onSelectAll(items: any){
|
|
115
|
+
console.log(items);
|
|
116
|
+
}
|
|
117
|
+
onDeSelectAll(items: any){
|
|
118
|
+
console.log(items);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Add the following component tag in you template
|
|
124
|
+
```html
|
|
125
|
+
<angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems"
|
|
126
|
+
[settings]="dropdownSettings"
|
|
127
|
+
(onSelect)="onItemSelect($event)"
|
|
128
|
+
(onDeSelect)="OnItemDeSelect($event)"
|
|
129
|
+
(onSelectAll)="onSelectAll($event)"
|
|
130
|
+
(onDeSelectAll)="onDeSelectAll($event)"></angular2-multiselect>
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
### Template - For custom html of menu item
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems" [settings]="dropdownSettings">
|
|
137
|
+
<c-item>
|
|
138
|
+
<ng-template let-item="item">
|
|
139
|
+
<label style="color: #333;min-width: 150px;">{{item.itemName}}</label>
|
|
140
|
+
<img [src]="item.image" style="width: 30px; border: 1px solid #efefef;margin-right: 20px;" />
|
|
141
|
+
<label>Capital - {{item.capital}}</label>
|
|
142
|
+
</ng-template>
|
|
143
|
+
</c-item>
|
|
144
|
+
</angular2-multiselect>
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Template - For custom html of Selected item - badge
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<angular2-multiselect [data]="dropdownList" [(ngModel)]="selectedItems" [settings]="dropdownSettings">
|
|
152
|
+
<c-badge>
|
|
153
|
+
<ng-template let-item="item">
|
|
154
|
+
<label style="margin: 0px;">{{item.itemName}}</label>
|
|
155
|
+
<img [src]="item.image" style="width: 16px; margin-right: 5px;" />
|
|
156
|
+
</ng-template>
|
|
157
|
+
</c-badge>
|
|
158
|
+
</angular2-multiselect>
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Template Driven Forms support
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
|
|
166
|
+
<form (ngSubmit)="onSubmit()" #loginForm="ngForm" style="border: 1px solid #ccc; padding: 10px;">
|
|
167
|
+
<div class="form-group">
|
|
168
|
+
<label for="name">Skills</label>
|
|
169
|
+
<angular2-multiselect [data]="itemList" [(ngModel)]="formModel.skills"
|
|
170
|
+
[settings]="settings"
|
|
171
|
+
(onSelect)="onItemSelect($event)"
|
|
172
|
+
(onDeSelect)="OnItemDeSelect($event)"
|
|
173
|
+
(onSelectAll)="onSelectAll($event)"
|
|
174
|
+
(onDeSelectAll)="onDeSelectAll($event)" name="skills">
|
|
175
|
+
</angular2-multiselect>
|
|
176
|
+
</div>
|
|
177
|
+
</form>
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
|
|
183
|
+
formModel = {
|
|
184
|
+
name: '',
|
|
185
|
+
email: 'ascasc@aa.com',
|
|
186
|
+
skills: [{ "id": 1, "itemName": "Angular" }]
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Reactive Forms support
|
|
192
|
+
|
|
193
|
+
```html
|
|
194
|
+
|
|
195
|
+
<form [formGroup]="userForm" novalidate style="border: 1px solid #ccc; padding: 10px;">
|
|
196
|
+
<div class="form-group">
|
|
197
|
+
<label for="name">Skills</label>
|
|
198
|
+
<angular2-multiselect [data]="itemList" [(ngModel)]="selectedItems"
|
|
199
|
+
[settings]="settings"
|
|
200
|
+
(onSelect)="onItemSelect($event)"
|
|
201
|
+
(onDeSelect)="OnItemDeSelect($event)"
|
|
202
|
+
(onSelectAll)="onSelectAll($event)"
|
|
203
|
+
(onDeSelectAll)="onDeSelectAll($event)" formControlName="skills">
|
|
204
|
+
</angular2-multiselect>
|
|
205
|
+
</div>
|
|
206
|
+
</form>
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
userForm: FormGroup;
|
|
212
|
+
this.userForm = this.fb.group({
|
|
213
|
+
name: '',
|
|
214
|
+
email: ['', Validators.required],
|
|
215
|
+
skills: [[], Validators.required]
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Settings
|
|
221
|
+
The following list of settings are supported by the component. Configure the settings to meet your requirement.
|
|
222
|
+
|
|
223
|
+
| Setting |Type | Description | Default Value |
|
|
224
|
+
|:--- |:--- |:--- |:--- |
|
|
225
|
+
| singleSelection | Boolean | To set the dropdown for single item selection only. | false |
|
|
226
|
+
| text | String | Text to be show in the dropdown, when no items are selected. | 'Select' |
|
|
227
|
+
| enableCheckAll | Boolean | Enable the option to select all items in list | false |
|
|
228
|
+
| selectAllText | String | Text to display as the label of select all option | Select All |
|
|
229
|
+
| unSelectAllText | String | Text to display as the label of unSelect option | UnSelect All |
|
|
230
|
+
| enableSearchFilter | Boolean | Enable filter option for the list. | false |
|
|
231
|
+
| maxHeight | Number | Set maximum height of the dropdown list in px. | 300 |
|
|
232
|
+
| badgeShowLimit | Number | Limit the number of badges/items to show in the input field. If not set will show all selected. | All |
|
|
233
|
+
| classes | String | Custom classes to the dropdown component. Classes are added to the dropdown selector tag. To add multiple classes, the value should be space separated class names.| '' |
|
|
234
|
+
| limitSelection | Number | Limit the selection of number of items from the dropdown list. Once the limit is reached, all unselected items gets disabled. | none |
|
|
235
|
+
| disabled | Boolean | Disable the dropdown | false |
|
|
236
|
+
| searchPlaceholderText | String | Custom text for the search placeholder text. Default value would be 'Search' | 'Search' |
|
|
237
|
+
| groupBy | String | Name of the field by which the list should be grouped. | none |
|
|
238
|
+
| searchAutofocus | Boolean | Autofocus search input field| true |
|
|
239
|
+
| labelKey | String | The property name which should be rendered as label in the dropdown| itemName |
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
### Callback Methods
|
|
243
|
+
- `onSelect` - Return the selected item on selection.
|
|
244
|
+
Example : (onSelect)="onItemSelect($event)"
|
|
245
|
+
- `onDeSelect` - Return the un-selected item on un-selecting.
|
|
246
|
+
Example : (onDeSelect)="OnItemDeSelect($event)"
|
|
247
|
+
- `onSelectAll` - Return the list of all selected items.
|
|
248
|
+
Example : (onSelectAll)="onSelectAll($event)"
|
|
249
|
+
- `onDeSelectAll` - Returns an empty array.
|
|
250
|
+
Example : (onDeSelectAll)="onDeSelectAll($event)"
|
|
251
|
+
- `onOpen` - Callback method fired after the dropdown opens
|
|
252
|
+
Example : (onOpen)="onOpen($event)"
|
|
253
|
+
- `onClose` - Callback method, fired when the dropdown is closed
|
|
254
|
+
Example : (onClose)="onClose($event)"
|
|
255
|
+
|
|
256
|
+
## Run locally
|
|
257
|
+
- Clone the repository or downlod the .zip,.tar files.
|
|
258
|
+
- Run `npm install`
|
|
259
|
+
- Run `ng serve` for a dev server
|
|
260
|
+
- Navigate to `http://localhost:4200/`
|
|
261
|
+
The app will automatically reload if you change any of the source files.
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
MIT License.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/app/angular2-multiselect-dropdown/multiselect.component';
|
package/gulpfile.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const gulp = require('gulp');
|
|
2
|
+
const sass = require('node-sass');
|
|
3
|
+
const inlineTemplates = require('gulp-inline-ng2-template');
|
|
4
|
+
const exec = require('child_process').exec;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Inline templates configuration.
|
|
8
|
+
* @see https://github.com/ludohenin/gulp-inline-ng2-template
|
|
9
|
+
*/
|
|
10
|
+
const INLINE_TEMPLATES = {
|
|
11
|
+
SRC: './src/app/angular2-multiselect-dropdown/**/*.ts',
|
|
12
|
+
DIST: './tmp/src-inlined',
|
|
13
|
+
CONFIG: {
|
|
14
|
+
base: '/src/app/angular2-multiselect-dropdown',
|
|
15
|
+
target: 'es6',
|
|
16
|
+
useRelativePaths: true,
|
|
17
|
+
styleProcessor: compileSass
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Inline external HTML and SCSS templates into Angular component files.
|
|
23
|
+
* @see: https://github.com/ludohenin/gulp-inline-ng2-template
|
|
24
|
+
*/
|
|
25
|
+
gulp.task('inline-templates', () => {
|
|
26
|
+
return gulp.src(INLINE_TEMPLATES.SRC)
|
|
27
|
+
.pipe(inlineTemplates(INLINE_TEMPLATES.CONFIG))
|
|
28
|
+
.pipe(gulp.dest(INLINE_TEMPLATES.DIST));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build ESM by running npm task.
|
|
33
|
+
* This is a temporary solution until ngc is supported --watch mode.
|
|
34
|
+
* @see: https://github.com/angular/angular/issues/12867
|
|
35
|
+
*/
|
|
36
|
+
gulp.task('build:esm', ['inline-templates'], (callback) => {
|
|
37
|
+
exec('npm run ngcompile', function (error, stdout, stderr) {
|
|
38
|
+
console.log(stdout, stderr);
|
|
39
|
+
callback(error)
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Implements ESM build watch mode.
|
|
45
|
+
* This is a temporary solution until ngc is supported --watch mode.
|
|
46
|
+
* @see: https://github.com/angular/angular/issues/12867
|
|
47
|
+
*/
|
|
48
|
+
gulp.task('build:esm:watch', ['build:esm'], () => {
|
|
49
|
+
gulp.watch('src/**/*', ['build:esm']);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
gulp.task('copy', () => {
|
|
53
|
+
return gulp.src(['package.json','LICENSE','README.md'])
|
|
54
|
+
.pipe(gulp.dest('dist/'));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Compile SASS to CSS.
|
|
59
|
+
* @see https://github.com/ludohenin/gulp-inline-ng2-template
|
|
60
|
+
* @see https://github.com/sass/node-sass
|
|
61
|
+
*/
|
|
62
|
+
function compileSass(path, ext, file, callback) {
|
|
63
|
+
let compiledCss = sass.renderSync({
|
|
64
|
+
data: file,
|
|
65
|
+
outputStyle: 'compressed',
|
|
66
|
+
});
|
|
67
|
+
callback(null, compiledCss.css);
|
|
68
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Simple Promiseify function that takes a Node API and return a version that supports promises.
|
|
10
|
+
* We use promises instead of synchronized functions to make the process less I/O bound and
|
|
11
|
+
* faster. It also simplifies the code.
|
|
12
|
+
*/
|
|
13
|
+
function promiseify(fn) {
|
|
14
|
+
return function () {
|
|
15
|
+
const args = [].slice.call(arguments, 0);
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
fn.apply(this, args.concat([function (err, value) {
|
|
18
|
+
if (err) {
|
|
19
|
+
reject(err);
|
|
20
|
+
} else {
|
|
21
|
+
resolve(value);
|
|
22
|
+
}
|
|
23
|
+
}]));
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const readFile = promiseify(fs.readFile);
|
|
29
|
+
const writeFile = promiseify(fs.writeFile);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Inline resources in a tsc/ngc compilation.
|
|
33
|
+
* @param projectPath {string} Path to the project.
|
|
34
|
+
*/
|
|
35
|
+
function inlineResources(projectPath) {
|
|
36
|
+
|
|
37
|
+
// Match only TypeScript files in projectPath.
|
|
38
|
+
const files = glob.sync('**/*.ts', {cwd: projectPath});
|
|
39
|
+
|
|
40
|
+
// For each file, inline the templates and styles under it and write the new file.
|
|
41
|
+
return Promise.all(files.map(filePath => {
|
|
42
|
+
const fullFilePath = path.join(projectPath, filePath);
|
|
43
|
+
return readFile(fullFilePath, 'utf-8')
|
|
44
|
+
.then(content => inlineResourcesFromString(content, url => {
|
|
45
|
+
// Resolve the template url.
|
|
46
|
+
return path.join(path.dirname(fullFilePath), url);
|
|
47
|
+
}))
|
|
48
|
+
.then(content => writeFile(fullFilePath, content))
|
|
49
|
+
.catch(err => {
|
|
50
|
+
console.error('An error occured: ', err);
|
|
51
|
+
});
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Inline resources from a string content.
|
|
57
|
+
* @param content {string} The source file's content.
|
|
58
|
+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
|
|
59
|
+
* @returns {string} The content with resources inlined.
|
|
60
|
+
*/
|
|
61
|
+
function inlineResourcesFromString(content, urlResolver) {
|
|
62
|
+
// Curry through the inlining functions.
|
|
63
|
+
return [
|
|
64
|
+
inlineTemplate,
|
|
65
|
+
inlineStyle
|
|
66
|
+
].reduce((content, fn) => fn(content, urlResolver), content);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and
|
|
71
|
+
* replace with `template: ...` (with the content of the file included).
|
|
72
|
+
* @param content {string} The source file's content.
|
|
73
|
+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
|
|
74
|
+
* @return {string} The content with all templates inlined.
|
|
75
|
+
*/
|
|
76
|
+
function inlineTemplate(content, urlResolver) {
|
|
77
|
+
return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function (m, templateUrl) {
|
|
78
|
+
const templateFile = urlResolver(templateUrl);
|
|
79
|
+
const templateContent = fs.readFileSync(templateFile, 'utf-8');
|
|
80
|
+
const shortenedTemplate = templateContent
|
|
81
|
+
.replace(/([\n\r]\s*)+/gm, ' ')
|
|
82
|
+
.replace(/"/g, '\\"');
|
|
83
|
+
return `template: "${shortenedTemplate}"`;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and
|
|
90
|
+
* replace with `styles: [...]` (with the content of the file included).
|
|
91
|
+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
|
|
92
|
+
* @param content {string} The source file's content.
|
|
93
|
+
* @return {string} The content with all styles inlined.
|
|
94
|
+
*/
|
|
95
|
+
function inlineStyle(content, urlResolver) {
|
|
96
|
+
return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function (m, styleUrls) {
|
|
97
|
+
const urls = eval(styleUrls);
|
|
98
|
+
return 'styles: ['
|
|
99
|
+
+ urls.map(styleUrl => {
|
|
100
|
+
const styleFile = urlResolver(styleUrl);
|
|
101
|
+
const styleContent = fs.readFileSync(styleFile, 'utf-8');
|
|
102
|
+
const shortenedStyle = styleContent
|
|
103
|
+
.replace(/([\n\r]\s*)+/gm, ' ')
|
|
104
|
+
.replace(/"/g, '\\"');
|
|
105
|
+
return `"${shortenedStyle}"`;
|
|
106
|
+
})
|
|
107
|
+
.join(',\n')
|
|
108
|
+
+ ']';
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = inlineResources;
|
|
113
|
+
module.exports.inlineResourcesFromString = inlineResourcesFromString;
|
|
114
|
+
|
|
115
|
+
// Run inlineResources if module is being called directly from the CLI with arguments.
|
|
116
|
+
if (require.main === module && process.argv.length > 2) {
|
|
117
|
+
console.log('Inlining resources from project:', process.argv[2]);
|
|
118
|
+
return inlineResources(process.argv[2]);
|
|
119
|
+
}
|