autofront 2.2.2 → 3.0.0

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.
Files changed (3) hide show
  1. package/README.md +55 -82
  2. package/index.js +500 -117
  3. package/package.json +41 -39
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Autofront
2
2
 
3
- Automatisation of front-end by [Gulp](https://gulpjs.com) and [Bower](https://bower.io).
3
+ Automation of front-end by [Gulp](https://gulpjs.com) and [Bower](https://bower.io).
4
4
 
5
5
  ## Get started
6
6
 
7
7
  ### Gulp
8
8
 
9
- Install its CLI, following [the official manual](https://gulpjs.com/docs/en/getting-started/quick-start/) but skipping [the local package](https://gulpjs.com/docs/en/getting-started/quick-start/#install-the-gulp-package-in-your-devdependencies) and the next steps.
9
+ Install its CLI (following [the official manual](https://gulpjs.com/docs/en/getting-started/quick-start/) but skipping [the local package](https://gulpjs.com/docs/en/getting-started/quick-start/#install-the-gulp-package-in-your-devdependencies) and the next steps).
10
10
 
11
11
  And put `gulpfile.js` simply with:
12
12
 
@@ -18,113 +18,86 @@ require('autofront');
18
18
 
19
19
  [Install it](https://bower.io/#install-bower), [initialize it and save dependencies](https://bower.io/#save-packages).
20
20
 
21
- ### Install
21
+ ### Installation
22
22
 
23
23
  ```sh
24
24
  npm install --save-dev autofront
25
25
  ```
26
26
 
27
- ### Main page
28
-
29
- In `src` directory, place `index.html` whose content would have to look basically like:
30
-
31
- ```html
32
- <!DOCTYPE html>
33
- <html>
34
- <head>
35
- <!-- build:css styles/vendor.css -->
36
- <!-- bower:css --><!-- endbower -->
37
- <!-- endbuild -->
38
- </head>
39
- <body>
40
- <!-- build:js scripts/vendor.js -->
41
- <!-- bower:js --><!-- endbower -->
42
- <!-- endbuild -->
43
- <!-- build:js scripts/app.js -->
44
- <!-- inject:js -->
45
- <!-- endinject -->
46
- <!-- endbuild -->
47
- </body>
48
- </html>
49
- ```
27
+ ### Source code
28
+
29
+ Place inside directory `src`; at least including the main page (`index.html`), without embedding tags (`<link>`s and `<script>`s).
50
30
 
51
31
  ### Run
52
32
 
53
- Finally initiate your project development:
33
+ Finally, initiate the project, commanding:
54
34
 
55
35
  ```sh
56
36
  gulp
57
37
  ```
58
38
 
59
- A browser tab will be opened. Then, try editing the HTML to view the web refresh.
39
+ A browser tab is opened. Now you are ready to develop!
60
40
 
61
- Other command options, that appear immediately below, are available. And to use another programming languages, see [the proper section](#support).
41
+ To reach further, see below.
62
42
 
63
43
  ## Usage
64
44
 
65
45
  ### Tasks
66
46
 
67
- Mainly the Gulp ones are the following:
68
-
69
- - `gulp` or `gulp serve` are for running a test server and develop with live reload.
70
- - `gulp build` only builds production code, the distributable application (`dist` folder).
71
- - With `gulp serve:dist`, a combination of the above is achieved: Specifically, the server runs that last version but without reload.
72
-
73
- ### Domains
74
-
75
- On executing Gulp command, an additional parameter can be included (e.g.: `gulp --dev` or `gulp build --pro`) to indicate the domain of connection path. Defaults to `--local`.
76
-
77
- These domain URLs would be searched in `package.json` listed in the property `domains` (optionally also `domainAliases`, to assign domain name for each alias).
78
-
79
- And, to capture the selected URL string, put `{{AUTOFRONT_DOMAIN}}` where it would be located in your source code.
80
-
81
- ## Support
82
-
83
- Positioning in source folder (`src`), you can utilize:
84
-
85
- ### HTML
86
-
87
- Besides of required `index.html`, it is possible to add more files. In this case, they will be treated as [templates](https://docs.angularjs.org/api/ng/directive/ngInclude) and, to work properly with `dist`, AngularJS must to be [appropriately](#angularjs) on.
47
+ The Gulp ones are:
88
48
 
89
- #### [Pug](https://pugjs.org)
49
+ | Name | Details | Processes |
50
+ | --- | --- | --- |
51
+ | `serve` (default) | Source code runs in a server with live reload. | <ul><li>Bower entry-point files catching.</li><li>Notification and injection of [environment](#environment-variables).</li><li>Compilation (Less, SCSS and Pug)[^1].</li><li>Set up[^2] of HTML5 mode.[^1]</li><li>Insertion of file with app info (`about.json`).</li></ul> |
52
+ | `build` | Production code is built (in folder `dist`). | The above and: <ul><li>Templates caching.[^1]</li><li>Concatenation to one hashed file (CSS and JS).</li><li>Minification (HTML, CSS, JS, images and JSON).</li><li>Console display of files size.</li></ul> |
53
+ | `serve:dist` | This distributable application is served but without the refreshing. | The same with the folder hidden. |
90
54
 
91
- Turn any hypertext file into Pug's one, except the mentioned untouchable index page.
55
+ [^1]: [If it is on](#settings).
56
+ [^2]: Invocation of [`$locationProvider`](https://docs.angularjs.org/api/ng/provider/$locationProvider#html5Mode) and a `<base>` injected.
92
57
 
93
- ### CSS
58
+ ### Environment variables
94
59
 
95
- Collocated in `styles` directory, type over lonely `index.css`.
60
+ They can be used in this way:
96
61
 
97
- #### [Less](https://lesscss.org)
62
+ 1. Define them. Look at [the next section](#settings).
63
+ 2. Put `AUTOFRONT_ENV` in your JS source code where it would be injected.
64
+ 3. On executing Gulp command, indicate the name of the current one to the flag argument `env`. Defaults to "development" with server tasks and to "production" with `build`.
98
65
 
99
- The same as before (but with its own file extension). The rest of optional files will be ignored if they are not [imported](https://lesscss.org/features/#import-atrules-feature).
66
+ ## Settings
100
67
 
101
- #### [Sass](https://sass-lang.com)
102
-
103
- Idem, but it is also obligatory an extra jointly: `_variables.scss`.
104
-
105
- ### JavaScript
106
-
107
- Wherever you want.
108
-
109
- #### [AngularJS](https://angularjs.org)
110
-
111
- One of modules should to be named "app", ideally the main one.
112
-
113
- Optionally, to work with [HTML5 mode](https://docs.angularjs.org/api/ng/provider/$locationProvider#html5Mode), invoke it:
68
+ You can configure it typing into Gulp file like this:
114
69
 
115
70
  ```js
116
- let autofront = require('autofront');
117
- autofront.html5Mode();
71
+ const autofront = require('autofront');
72
+
73
+ autofront.property = {
74
+ subproperty: value,
75
+ subproperty2: {
76
+ subproperty3: value2,
77
+ // ...
78
+ },
79
+ // ...
80
+ };
81
+ autofront.property2.subproperty4 = value3;
82
+ // ...
118
83
  ```
119
84
 
120
- ### Others
121
-
122
- Any asset (e.g. a PDF document) will keep the location path and, particularly at production, will take place an images optimization.
123
-
124
- ## Pending
125
-
126
- Fixes and improvements to do:
127
-
128
- - Once the server watch for changes, synchronize also the deletion of source files.
129
- - Replace Bower as dependency manager.
130
- - Migrate AngularJS to new [Angular](https://angular.io).
85
+ Defining with:
86
+
87
+ | Property | Subprop. | | Type | Details | Default |
88
+ | --- | --- | --- | --- | --- | --- |
89
+ | `html` | `pug` | | Boolean | [Pug](https://pugjs.org) activated? | `false` |
90
+ | `css` | `folder` | | String | Directory that contains CSS files. | `'styles/'` |
91
+ | <!-- --> | `filename` | | String | Filename of root files. | `'index'` |
92
+ | <!-- 〃 --> | `order` | | Number | Index of order to include content in stylesheet. | `0` |
93
+ | <!-- --> | `less`[^3] | `order` | Number | Idem for [Less](https://lesscss.org). | `1` |
94
+ | <!-- --> | `scss`[^3] | `order` | Number | Idem for [SCSS (Sass)](https://sass-lang.com/documentation/syntax#scss). | `2` |
95
+ | <!-- --> | <!-- 〃 --> | `variables` | String | Filename of variables file. | `_variables` |
96
+ | <!-- 〃 --> | `fonts` | `folder` | String | Location (folder path) of font files from Bower. | `'fonts/'` |
97
+ | <!-- 〃 --> | <!-- 〃 --> | `extensions` | String or array of strings | File extensions to catch. | `['eot', 'otf', 'svg', 'ttf', 'woff', 'woff2']` |
98
+ | `js` | `ng`[^3] | `module` | String | Name of [AngularJS](https://angularjs.org) main module. | `'app'` |
99
+ | <!-- 〃 --> | <!-- 〃 --> | `html5Mode` | Boolean | [HTML5 mode](https://docs.angularjs.org/guide/$location#html5-mode) enabled? | `false` |
100
+ | <!-- 〃 --> | <!-- 〃 --> | `template` | Boolean | Templates loaded by [`$templateCache`](https://docs.angularjs.org/api/ng/service/$templateCache)? | `true` |
101
+ | <!-- 〃 --> | `envs` | | Object | Environment variables list, with names as keys and data (whatever can be JSON parsed) as values. | `{}` |
102
+
103
+ [^3]: It can be disabled assigning a falsy value.
package/index.js CHANGED
@@ -1,153 +1,536 @@
1
- this.html5Mode = html5Mode;
1
+ const defSettings = {
2
+ html: { pug: false },
3
+ css: {
4
+ folder: 'styles/',
5
+ filename: 'index',
6
+ order: 0,
7
+ less: { order: 1 },
8
+ scss: {
9
+ order: 2,
10
+ variables: '_variables'
11
+ },
12
+ fonts: {
13
+ folder: 'fonts/',
14
+ extensions: ['eot', 'otf', 'svg', 'ttf', 'woff', 'woff2']
15
+ }
16
+ },
17
+ js: {
18
+ ng: {
19
+ module: 'app',
20
+ html5Mode: false,
21
+ template: true
22
+ },
23
+ envs: {}
24
+ }
25
+ };
26
+ const settings = this;
27
+ for (const name in defSettings)
28
+ settings[name] = { ...defSettings[name] };
2
29
 
3
30
  const gulp = require('gulp'),
4
- path = require('path'),
5
- args = require('get-gulp-args')(),
6
- mergeStream = require('merge-stream'),
7
- mainBowerFiles = require('main-bower-files'),
8
31
  $ = require('gulp-load-plugins')(),
9
- injStr = $.injectString,
10
- gulpSass = $.sass(require('sass')),
11
32
  notifyError = $.notify.onError(error => error.message),
12
- browserSync = require('browser-sync').create();
33
+ gulpFilter = ext => $.filter(getGlob(ext), { restore: true }),
34
+ browserSync = require('browser-sync').create(),
35
+ deleteEmpty = require('delete-empty'),
36
+ gulpHtmlmin = () => $.htmlmin({ collapseWhitespace: true, conservativeCollapse: true }),
37
+ fs = require('fs'),
38
+ hidefile = require('hidefile');
13
39
 
14
- let domain = undefined;
40
+ let defEnv = 'production',
41
+ envName,
42
+ envValue;
15
43
 
16
- const allFiles = getFiles(),
17
- indexHtmlFile = 'index.html',
18
- cssFilename = 'index',
19
- cssFullFilename = cssFilename + '.css';
20
- let stylesFolder = 'styles/',
21
- jsTemplatesFile = 'scripts/templates.js';
44
+ const allFiles = getGlob(),
45
+ indexFile = 'index.html',
46
+ scriptsDir = 'scripts/',
47
+ jsFiles = getGlob('js'),
48
+ cssComment = '<!-- autofrontcss -->',
49
+ endCssComment = '<!-- endautofrontcss -->',
50
+ jsComment = '<!-- autofrontjs -->',
51
+ html5ModeJsFile = scriptsDir + 'html5-mode.js',
52
+ jsTemplatesFile = scriptsDir + 'templates.js',
53
+ endJsComment = '<!-- endautofrontjs -->',
54
+ cssFile = 'index.css',
55
+ jsFile = 'index.js';
56
+ let stylesDir,
57
+ stylesFilename,
58
+ stylesCssFile,
59
+ cssExtensions = [];
22
60
 
23
- const paths = {
61
+ const globs = {
24
62
  src: 'src/',
25
63
  tmp: '.tmp/',
26
64
  dist: 'dist/'
27
65
  };
28
- paths.srcIndexHtml = paths.src + indexHtmlFile;
29
- paths.srcCss = paths.src + stylesFolder + cssFullFilename;
30
- paths.srcSass = paths.src + getFiles('scss');
31
- paths.srcLess = paths.src + getFiles('less');
32
- paths.srcJs = paths.src + getFiles('js');
33
- paths.srcOthers = [paths.src + allFiles, '!' + paths.srcIndexHtml, '!' + paths.srcCss, '!' + paths.srcSass, '!' + paths.srcLess, '!' + paths.srcJs];
34
-
35
- const nl = '\n',
66
+ globs.hiddenDist = '.' + globs.dist;
67
+ globs.srcIndex = globs.src + indexFile;
68
+ globs.srcJs = globs.src + jsFiles;
69
+ globs.srcOthers = [globs.src + allFiles];
70
+ globs.tmpAllFiles = globs.tmp + allFiles;
71
+ globs.distIndexFile = globs.dist + indexFile;
72
+ globs.distTmpls = [globs.dist + getGlob('html'), '!' + globs.distIndexFile];
73
+
74
+ const nl = '\r\n',
36
75
  tab = ' ';
37
76
 
38
- gulp.task('check', () => {
39
- const pckg = require(path.resolve('package.json')),
40
- domains = pckg.domains;
41
- let domainIndex = args[0] || 'local';
42
- if (domains) {
43
- const domainAliases = pckg.domainAliases;
44
- if (domainAliases) {
45
- const alias = domainAliases[domainIndex];
46
- if (alias)
47
- domainIndex = alias;
77
+ function setDefaultEnv(cb) {
78
+ defEnv = 'development';
79
+ cb();
80
+ }
81
+ setDefaultEnv.displayName = 'set-default-env';
82
+
83
+ function setVariables(cb) {
84
+ stylesDir = getSetting('cssFolder');
85
+ stylesFilename = getSetting('filename');
86
+ stylesCssFile = stylesDir + cssFile;
87
+
88
+ for (const cssExt of [
89
+ {
90
+ name: 'css',
91
+ process: $.cssimport
92
+ },
93
+ {
94
+ name: 'less',
95
+ process: $.less,
96
+ isPreprocessor: true
97
+ },
98
+ {
99
+ name: 'scss',
100
+ process: $.sass(require('sass')),
101
+ getExtraCode: () => {
102
+ const file = globs.src + stylesDir + getSetting('variables') + '.scss';
103
+ return fileExists(file) ? `@import "${file}";` : '';
104
+ },
105
+ isPreprocessor: true
48
106
  }
49
- domain = domains[domainIndex];
107
+ ]) {
108
+ const name = cssExt.name;
109
+ if (!cssExt.isPreprocessor || getSetting(name))
110
+ cssExtensions.push({ getExtraCode: () => '', ...cssExt, order: getSetting(name + 'Order') });
50
111
  }
51
- const isMatched = domain !== undefined;
52
- return gulp.src(paths.src)
53
- .pipe($.notify(isMatched ? `Matching domain: "${domainIndex}".` : 'No domain matched.'));
54
- });
55
-
56
- gulp.task('del', () => delFolder(paths.tmp));
57
- gulp.task('index-build', () => gulp.src(paths.srcIndexHtml).pipe(injStr.after('<!-- endbuild -->', nl + tab + `<link rel="stylesheet" href="${stylesFolder}${cssFullFilename}">`)).pipe($.inject(gulp.src(paths.srcJs).pipe($.angularFilesort()), { relative: true })).on('error', notifyError).pipe($.wiredep()).pipe($.useref()).pipe(gulp.dest(paths.tmp)));
58
- gulp.task('index-domain', () => gulp.src(paths.tmp + getFiles('js')).pipe(injStr.replace('{{AUTOFRONT_DOMAIN}}', domain)).pipe(gulp.dest(paths.tmp)));
59
- gulp.task('index', gulp.series('index-build', 'index-domain'));
60
- gulp.task('styles', () => {
61
- return mergeStream(getCssStream('css'), getCssStream('scss', gulpSass, '@import "variables";'), getCssStream('less', $.less))
62
- .pipe($.concat(cssFullFilename))
63
- .pipe(gulp.dest(paths.tmp + stylesFolder))
64
- .pipe(browserSync.stream());
65
-
66
- function getCssStream(ext, process, extraCode) {
67
- let stream = gulp.src(paths.src + stylesFolder + cssFilename + '.' + ext, { allowEmpty: true });
68
- if (process)
69
- return stream.pipe(injStr.prepend((extraCode ? extraCode + nl : '') + '// bower:' + ext + nl + '// endbower' + nl)).pipe($.wiredep()).pipe(process()).on('error', notifyError);
70
- return stream;
112
+ cssExtensions = cssExtensions.sort((a, b) => a.order - b.order);
113
+
114
+ const srcStyles = [];
115
+ for (const cssExt of cssExtensions) {
116
+ const glob = globs.src + getGlob(cssExt.name);
117
+ srcStyles.push(glob);
118
+ cssExt.glob = glob;
71
119
  }
72
- });
73
- gulp.task('fonts', () => gulp.src(mainBowerFiles()).pipe(filter(['eot', 'otf', 'svg', 'ttf', 'woff', 'woff2'], true)).pipe(gulp.dest(paths.tmp + 'fonts/')));
74
- gulp.task('others', () => {
75
- const pugFilter = filter('pug');
76
- return gulp.src(paths.srcOthers)
77
- .pipe(pugFilter).pipe($.pug()).on('error', notifyError).pipe(pugFilter.restore)
78
- .pipe(gulp.dest(paths.tmp));
79
- });
80
- gulp.task('about', () => gulp.src('package.json').pipe($.about()).pipe(gulp.dest(paths.tmp)));
81
- gulp.task('build:tmp', gulp.series('del', 'check', gulp.parallel('index', 'styles', 'fonts', 'others', 'about')));
82
- gulp.task('browser', gulp.series('build:tmp', (cb) => {
83
- browserSyncInit(paths.tmp);
120
+ globs.srcOthers.push(...[globs.srcIndex, globs.srcJs, ...srcStyles].map(glob => '!' + glob));
121
+
84
122
  cb();
85
- }));
86
- gulp.task('serve', gulp.series('browser', () => {
87
- gulp.watch([paths.srcIndexHtml, paths.srcJs], gulp.task('index'));
88
- gulp.watch([paths.srcCss, paths.srcSass, paths.srcLess], gulp.task('styles'));
89
- gulp.watch(paths.srcOthers, gulp.task('others'));
90
- gulp.watch([paths.tmp + allFiles, '!' + paths.tmp + stylesFolder + cssFullFilename], function (cb) {
91
- browserSync.reload();
92
- cb();
123
+ }
124
+ setVariables.displayName = 'set-variables';
125
+
126
+ function getEnv() {
127
+ envName = require('get-gulp-args')().env || defEnv;
128
+ envValue = getSetting('envs')[envName];
129
+ const isMatched = envValue !== undefined;
130
+ return gulp.src(globs.src, { read: false })
131
+ .pipe($.notify(isMatched ? `Matching environment: "${envName}".` : 'No environment matched.'));
132
+ }
133
+ getEnv.displayName = 'get-env';
134
+
135
+ function removeFolder() {
136
+ return delDir(globs.tmp);
137
+ }
138
+ removeFolder.displayName = 'remove-folder';
139
+
140
+ function createFolder() {
141
+ return gulp.src('*.*', { read: false })
142
+ .pipe(gulp.dest(globs.tmp));
143
+ }
144
+ createFolder.displayName = 'create-folder';
145
+
146
+ function hideFolder(cb) {
147
+ hideDir(globs.tmp);
148
+ cb();
149
+ }
150
+ hideFolder.displayName = 'hide-folder';
151
+
152
+ const addFolder = gulp.series(createFolder, hideFolder);
153
+
154
+ function index() {
155
+ const filename = 'vendor',
156
+ strs = [
157
+ cssComment,
158
+ `<!-- build:css ${stylesDir + filename}.css -->`,
159
+ '<!-- bower:css --><!-- endbower -->',
160
+ '<!-- endbuild -->'
161
+ ];
162
+ for (const { name } of cssExtensions)
163
+ strs.push('<link rel="stylesheet" href="' + stylesDir + stylesFilename + (name != 'css' ? '.' + name : '') + '.css' + '">');
164
+ strs.push(
165
+ endCssComment,
166
+ jsComment,
167
+ `<!-- build:js ${scriptsDir + filename}.js defer -->`,
168
+ '<!-- bower:js --><!-- endbower -->',
169
+ '<!-- endbuild -->',
170
+ '<!-- inject:js -->',
171
+ '<!-- endinject -->'
172
+ );
173
+ if (getSetting('html5Mode')) {
174
+ strs.unshift('<base href="/">');
175
+ strs.push(getScriptTag(html5ModeJsFile));
176
+ }
177
+ strs.push(endJsComment);
178
+
179
+ let stream = gulp.src(globs.srcJs);
180
+ if (getSetting('ng'))
181
+ stream = stream.pipe($.angularFilesort());
182
+
183
+ return gulp.src(globs.srcIndex)
184
+ .pipe($.injectString.before('</head>', tab + strs.join(nl + tab) + nl))
185
+ .pipe($.inject(stream, { relative: true, transform: filepath => getScriptTag(filepath) })).on('error', notifyError)
186
+ .pipe($.wiredep())
187
+ .pipe($.useref())
188
+ .pipe(gulp.dest(globs.tmp));
189
+ }
190
+
191
+ function js() {
192
+ return gulp.src(globs.srcJs)
193
+ .pipe(replace('AUTOFRONT_ENV', JSON.stringify(envValue, undefined, tab)))
194
+ .pipe(gulp.dest(globs.tmp));
195
+ }
196
+
197
+ const indexAndJs = gulp.parallel(index, js);
198
+
199
+ const css = getStylesTask('css');
200
+
201
+ const less = getStylesTask('less');
202
+
203
+ const scss = getStylesTask('scss');
204
+
205
+ const styles = gulp.parallel(css, less, scss);
206
+
207
+ function html5Mode(cb) {
208
+ if (getSetting('html5Mode'))
209
+ return $.addFiles([{
210
+ name: html5ModeJsFile,
211
+ content: `(function () {
212
+ angular.module('${getSetting('module')}')
213
+ .config(config);
214
+
215
+ function config($locationProvider) {
216
+ $locationProvider.html5Mode(true);
217
+ }
218
+ })();`
219
+ }])
220
+ .pipe(gulp.dest(globs.tmp));
221
+
222
+ cb();
223
+ }
224
+ html5Mode.displayName = 'html5-mode';
225
+
226
+ function fonts(cb) {
227
+ const glob = require('main-bower-files')(getGlob(getSetting('extensions')));
228
+ if (glob.length)
229
+ return gulp.src(glob)
230
+ .pipe(gulp.dest(globs.tmp + getSetting('fontsFolder')));
231
+
232
+ cb();
233
+ }
234
+
235
+ function others() {
236
+ let stream = gulp.src(globs.srcOthers);
237
+ if (getSetting('pug')) {
238
+ const pugFilter = gulpFilter('pug');
239
+ stream = stream.pipe(pugFilter).pipe($.pug()).on('error', notifyError).pipe(pugFilter.restore);
240
+ }
241
+ return stream.pipe(gulp.dest(globs.tmp));
242
+ }
243
+
244
+ function about() {
245
+ return gulp.src('package.json')
246
+ .pipe($.about({ inject: { environment: envName } }))
247
+ .pipe(gulp.dest(globs.tmp));
248
+ }
249
+
250
+ const buildTmp = gulp.series(
251
+ gulp.parallel(getEnv, removeFolder),
252
+ addFolder,
253
+ gulp.parallel(indexAndJs, styles, html5Mode, fonts, others, about)
254
+ );
255
+
256
+ function browser(cb) {
257
+ browserSyncInit(globs.tmp);
258
+ cb();
259
+ }
260
+
261
+ function reload(cb) {
262
+ browserSync.reload();
263
+ cb();
264
+ }
265
+
266
+ function watch() {
267
+ gulp.watch(globs.srcIndex, index);
268
+ gulp.watch(globs.srcJs)
269
+ .on('add', indexAndJs)
270
+ .on('change', gulp.series(js))
271
+ .on('unlink', gulp.series(index))
272
+ .on('unlink', path => { delFile(path); });
273
+
274
+ for (cssExt of cssExtensions)
275
+ gulp.watch(cssExt.glob, eval(cssExt.name));
276
+
277
+ gulp.watch(globs.srcOthers)
278
+ .on('add', gulp.series(others))
279
+ .on('change', gulp.series(others))
280
+ .on('unlink', path => { delFile(path, replaceExt); });
281
+
282
+ gulp.watch([globs.tmpAllFiles, '!' + globs.tmp + stylesDir + getGlob('css')], reload).on('unlink', () => { deleteEmpty(globs.tmp); });
283
+
284
+ function delFile(path, fn) {
285
+ path = path.replaceAll('\\', '/').replace(globs.src, globs.tmp);
286
+ if (fn)
287
+ path = fn(path);
288
+ gulp.src(path, { read: false })
289
+ .pipe($.clean());
290
+ }
291
+
292
+ function replaceExt(path) {
293
+ if (getSetting('pug'))
294
+ return path.replace('.pug', '.html');
295
+ return path;
296
+ }
297
+ }
298
+
299
+ gulp.task('serve', gulp.series(
300
+ gulp.parallel(setDefaultEnv, setVariables),
301
+ buildTmp, browser, watch
302
+ ));
303
+
304
+ function removeFolderDist() {
305
+ return delDir([globs.dist, globs.hiddenDist]);
306
+ }
307
+ removeFolderDist.displayName = 'remove-folder:dist';
308
+
309
+ function copy() {
310
+ return gulp.src(globs.tmpAllFiles)
311
+ .pipe($.size())
312
+ .pipe(gulp.dest(globs.dist));
313
+ }
314
+
315
+ function templates() {
316
+ let stream = gulp.src(globs.distTmpls)
317
+ .pipe(gulpHtmlmin());
318
+ if (getSetting('template'))
319
+ stream = stream.pipe($.angularTemplatecache(jsTemplatesFile, { module: getSetting('module'), transformUrl: url => url.slice(1) }));
320
+ return stream.pipe(gulp.dest(globs.dist));
321
+ }
322
+
323
+ function indexDist() {
324
+ const replaces = Object.entries({
325
+ [cssComment]: `<!-- build:css ${stylesCssFile} -->`,
326
+ [endCssComment]: '<!-- endbuild -->',
327
+ [jsComment]: `<!-- build:js ${jsFile} defer -->`,
328
+ [endJsComment]: '<!-- endbuild -->'
93
329
  });
94
- }));
95
-
96
- gulp.task('del:dist', () => delFolder(paths.dist));
97
- gulp.task('copy', gulp.series('del:dist', () => gulp.src(paths.tmp + allFiles).pipe(gulp.dest(paths.dist))));
98
- gulp.task('templates-build', () => gulp.src([paths.dist + getFiles('html'), '!' + paths.dist + indexHtmlFile]).pipe($.cleanDest(paths.dist)).pipe(minifyHtml()).pipe($.angularTemplatecache(jsTemplatesFile, { module: 'app', transformUrl: function (url) { return url.slice(1); } })).pipe(gulp.dest(paths.dist)));
99
- gulp.task('templates-clean', () => require('delete-empty')(paths.dist));
100
- gulp.task('templates', gulp.series('templates-build', 'templates-clean'));
101
- gulp.task('build', gulp.series('build:tmp', 'copy', 'templates', () => {
102
- const indexHtmlFilter = filter('html'),
103
- cssFilter = filter('css'),
104
- jsFilter = filter('js'),
105
- cssAndJsFilter = filter(['css', 'js']),
106
- imgFilter = filter(['png', 'jpg', 'gif', 'svg']),
107
- jsonFilter = filter('json');
108
- return gulp.src(paths.dist + allFiles)
109
- .pipe(indexHtmlFilter).pipe(injStr.before('</body>', `<script src="${jsTemplatesFile}"></script>` + nl)).pipe(minifyHtml()).pipe(indexHtmlFilter.restore)
110
- .pipe(cssFilter).pipe($.cssnano({ zindex: false })).pipe(cssFilter.restore)
111
- .pipe(jsFilter).pipe($.ngAnnotate()).pipe($.terser()).pipe(jsFilter.restore)
330
+ let stream = gulp.src(globs.distIndexFile);
331
+ if (getSetting('template') && fileExists(globs.dist + jsTemplatesFile))
332
+ stream = stream.pipe($.injectString.before(endJsComment, getScriptTag(jsTemplatesFile) + nl + tab));
333
+ for (const [search, str] of replaces)
334
+ stream = stream.pipe($.injectString.replace(search, str));
335
+ return stream
336
+ .pipe($.useref())
337
+ .pipe(gulp.dest(globs.dist));
338
+ }
339
+ indexDist.displayName = 'index:dist';
340
+
341
+ function rebaseCss() {
342
+ return gulp.src(globs.dist + stylesCssFile)
343
+ .pipe($.rebaseCssUrls(globs.dist))
344
+ .pipe(gulp.dest(globs.dist));
345
+ }
346
+ rebaseCss.displayName = 'rebase-css';
347
+
348
+ function rebaseHtml() {
349
+ return gulp.src(globs.distIndexFile)
350
+ .pipe($.injectString.replace(` href="${stylesCssFile}"`, ` href="${cssFile}"`))
351
+ .pipe(gulp.dest(globs.dist));
352
+ }
353
+ rebaseHtml.displayName = 'rebase-html';
354
+
355
+ const rebase = gulp.parallel(rebaseCss, rebaseHtml);
356
+
357
+ function cleanFiles() {
358
+ return gulp.src([
359
+ ...(getSetting('template') ? globs.distTmpls : []),
360
+ globs.dist + getGlob('css'), '!' + globs.dist + cssFile,
361
+ globs.dist + jsFiles, '!' + globs.dist + jsFile
362
+ ], { read: false })
363
+ .pipe($.clean());
364
+ }
365
+ cleanFiles.displayName = 'clean-files';
366
+
367
+ function cleanFolders() {
368
+ return deleteEmpty(globs.dist);
369
+ }
370
+ cleanFolders.displayName = 'clean-folders';
371
+
372
+ const clean = gulp.series(cleanFiles, cleanFolders);
373
+
374
+ const minify = gulp.parallel(
375
+ getMinifyTask('html', stream => stream.pipe(gulpHtmlmin())),
376
+ getMinifyTask('css', stream => stream.pipe($.postcss([require('cssnano')()]))),
377
+ getMinifyTask('js', stream => {
378
+ if (getSetting('ng'))
379
+ stream = stream.pipe($.ngAnnotate());
380
+ return stream.pipe($.terser());
381
+ }),
382
+ getMinifyTask(['png', 'jpg', 'gif', 'svg'], stream => stream.pipe($.imagemin()), 'img'),
383
+ getMinifyTask('json', stream => stream.pipe($.jsonmin()))
384
+ );
385
+
386
+ function finishBuild() {
387
+ const cssAndJsFilter = gulpFilter(['css', 'js']);
388
+ return gulp.src(globs.dist + allFiles)
112
389
  .pipe(cssAndJsFilter).pipe($.rev()).pipe($.revDeleteOriginal()).pipe(cssAndJsFilter.restore)
113
390
  .pipe($.revReplace())
114
- .pipe(imgFilter).pipe($.imagemin()).pipe(imgFilter.restore)
115
- .pipe(jsonFilter).pipe($.jsonmin()).pipe(jsonFilter.restore)
116
391
  .pipe($.size({ showFiles: true }))
117
- .pipe(gulp.dest(paths.dist));
118
- }));
119
- gulp.task('serve:dist', gulp.series('build', () => browserSyncInit(paths.dist)));
392
+ .pipe(gulp.dest(globs.dist));
393
+ }
394
+ finishBuild.displayName = 'finish-build';
395
+
396
+ gulp.task('build', gulp.series(
397
+ setVariables,
398
+ gulp.parallel(buildTmp, removeFolderDist),
399
+ copy, templates, indexDist, rebase, clean, minify, finishBuild
400
+ ));
401
+
402
+ function hideFolderDist(cb) {
403
+ hideDir(globs.dist);
404
+ cb();
405
+ }
406
+ hideFolderDist.displayName = 'hide-folder:dist';
407
+
408
+ function browserDist(cb) {
409
+ browserSyncInit(globs.hiddenDist);
410
+ cb();
411
+ }
412
+ browserDist.displayName = 'browser:dist';
413
+
414
+ gulp.task('serve:dist', gulp.series(setDefaultEnv, 'build', hideFolderDist, browserDist));
415
+
416
+ gulp.task('default', gulp.series('serve'));
417
+
418
+ function getGlob(ext = '*') {
419
+ const glob = '**/*.';
420
+ if (typeof ext == 'string')
421
+ return glob + ext;
422
+ return glob + '{' + ext.join() + ',}';
423
+ }
424
+
425
+ function getSetting(name) {
426
+ switch (name) {
427
+ case 'pug':
428
+ return getValue('html');
429
+ case 'cssFolder':
430
+ case 'filename':
431
+ case 'cssOrder':
432
+ return getValue('css');
433
+ case 'less':
434
+ case 'scss':
435
+ return getValue('css', true);
436
+ case 'lessOrder':
437
+ return getValue('css.less', true, true);
438
+ case 'scssOrder':
439
+ case 'variables':
440
+ return getValue('css.scss', true, true);
441
+ case 'fontsFolder':
442
+ case 'extensions':
443
+ return getValue('css.fonts');
444
+ case 'ng':
445
+ return getValue('js', true);
446
+ case 'module':
447
+ case 'html5Mode':
448
+ case 'template':
449
+ return getValue('js.ng', true, true);
450
+ case 'envs':
451
+ return getValue('js');
452
+ }
120
453
 
121
- gulp.task('default', gulp.task('serve'));
454
+ function getValue(str, withoutDefault, onlyIfFalsy) {
455
+ for (const str of ['Folder', 'Order'])
456
+ if (name.endsWith(str))
457
+ name = str.toLowerCase();
122
458
 
123
- function html5Mode() {
124
- const pathPrefix = '/';
125
- stylesFolder = pathPrefix + stylesFolder;
126
- jsTemplatesFile = pathPrefix + jsTemplatesFile;
459
+ const nameStr = str + '.' + name,
460
+ value = eval('settings.' + nameStr.replaceAll('.', '?.'));
461
+ if (withoutDefault) {
462
+ if (!onlyIfFalsy || !getSetting(str.split('.').pop()))
463
+ return value;
464
+ }
465
+ return value ?? eval('defSettings.' + nameStr);
466
+ }
127
467
  }
128
468
 
129
- function getFiles(ext = '*') {
130
- const isArray = typeof ext != 'string';
131
- return '**/*.' + (isArray ? '{' : '') + (isArray ? ext.join() : ext) + (isArray ? '}' : '');
469
+ function fileExists(path) {
470
+ return fs.existsSync(path);
132
471
  }
133
472
 
134
- function delFolder(path) {
135
- return gulp.src(path, { allowEmpty: true, read: false })
473
+ function delDir(glob) {
474
+ return gulp.src(glob, { allowEmpty: true, read: false })
136
475
  .pipe($.clean());
137
476
  }
138
477
 
139
- function filter(ext, isUnrestored) {
140
- return $.filter(getFiles(ext), { restore: !isUnrestored });
478
+ function hideDir(glob) {
479
+ hidefile.hideSync(glob, error => notifyError(error));
141
480
  }
142
481
 
143
- function browserSyncInit(path) {
144
- browserSync.init({
145
- server: {
146
- baseDir: path
482
+ function getScriptTag(src) {
483
+ return `<script src="${src}" defer></script>`;
484
+ }
485
+
486
+ function replace(search, str) {
487
+ for (const char of ['$', '.', '/', '('])
488
+ search = search.replaceAll(char, '\\' + char);
489
+ return $.injectString.replace(search, str);
490
+ }
491
+
492
+ function getStylesTask(ext) {
493
+ const fn = cb => {
494
+ const cssExt = cssExtensions.find(({ name }) => name == ext);
495
+ if (cssExt) {
496
+ const stylesFile = stylesFilename + '.' + ext,
497
+ srcStylesFile = globs.src + stylesDir + stylesFile,
498
+ isPreprocessor = cssExt.isPreprocessor,
499
+ extraCode = cssExt.getExtraCode(),
500
+ sep = nl + nl,
501
+ content = (extraCode ? extraCode + sep : '') + (isPreprocessor ? '// bower:' + ext + nl + '// endbower' : '');
502
+ let stream;
503
+ if (!fileExists(srcStylesFile))
504
+ stream = $.addFiles([{
505
+ name: stylesFile,
506
+ content
507
+ }]);
508
+ else
509
+ stream = gulp.src(srcStylesFile)
510
+ .pipe($.injectString.prepend(content ? content + sep : ''));
511
+ if (isPreprocessor)
512
+ stream = stream.pipe($.wiredep());
513
+ stream = stream.pipe(cssExt.process()).on('error', notifyError);
514
+ if (isPreprocessor)
515
+ stream = stream.pipe($.rename({ suffix: '.' + ext }));
516
+ return stream
517
+ .pipe(gulp.dest(globs.tmp + stylesDir))
518
+ .pipe(browserSync.stream());
147
519
  }
148
- });
520
+
521
+ cb();
522
+ };
523
+ fn.displayName = ext;
524
+ return fn;
525
+ }
526
+
527
+ function browserSyncInit(path) {
528
+ browserSync.init({ server: path });
149
529
  }
150
530
 
151
- function minifyHtml() {
152
- return $.htmlmin({ collapseWhitespace: true, conservativeCollapse: true });
531
+ function getMinifyTask(ext, getProcessedStream, str) {
532
+ const fn = () => getProcessedStream(gulp.src(globs.dist + getGlob(ext)))
533
+ .pipe(gulp.dest(globs.dist));
534
+ fn.displayName = 'minify-' + (str || ext);
535
+ return fn;
153
536
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "autofront",
3
- "version": "2.2.2",
4
- "description": "Automatisation of front-end by Gulp and Bower.",
3
+ "version": "3.0.0",
4
+ "description": "Automation of front-end by Gulp and Bower.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "serve": "gulp",
8
- "serve:dist": "gulp serve:dist",
9
- "build": "gulp build",
10
- "test": "echo \"Error: no test specified\" && exit 1"
8
+ "serve:dist": "gulp serve:dist --env=preproduction",
9
+ "build": "gulp build"
11
10
  },
12
11
  "repository": {
13
12
  "type": "git",
@@ -18,7 +17,7 @@
18
17
  "pug",
19
18
  "css",
20
19
  "less",
21
- "sass",
20
+ "scss",
22
21
  "javascript",
23
22
  "angularjs"
24
23
  ],
@@ -29,38 +28,41 @@
29
28
  },
30
29
  "homepage": "https://github.com/mvicens/autofront#readme",
31
30
  "dependencies": {
32
- "browser-sync": "^2.26.3",
33
- "delete-empty": "^2.0.0",
34
- "get-gulp-args": "^0.0.1",
35
- "gulp": "^4.0.2",
36
- "gulp-about": "^1.1.0",
37
- "gulp-angular-filesort": "^1.2.1",
38
- "gulp-angular-templatecache": "^2.2.3",
39
- "gulp-clean": "^0.4.0",
40
- "gulp-clean-dest": "^0.2.0",
41
- "gulp-concat": "^2.6.1",
42
- "gulp-cssnano": "^2.1.3",
43
- "gulp-filter": "^5.1.0",
44
- "gulp-htmlmin": "^4.0.0",
45
- "gulp-imagemin": "^4.1.0",
46
- "gulp-inject": "^4.3.2",
47
- "gulp-inject-string": "^1.1.1",
48
- "gulp-jsonmin": "^1.2.0",
49
- "gulp-less": "^3.5.0",
50
- "gulp-load-plugins": "^1.5.0",
51
- "gulp-ng-annotate": "^2.1.0",
52
- "gulp-notify": "^3.2.0",
53
- "gulp-pug": "^4.0.1",
54
- "gulp-rev": "^8.1.1",
55
- "gulp-rev-delete-original": "^0.2.3",
56
- "gulp-rev-replace": "^0.4.4",
57
- "gulp-sass": "^5.0.0",
58
- "gulp-size": "^3.0.0",
59
- "gulp-terser": "^1.1.7",
60
- "gulp-useref": "^3.1.6",
61
- "gulp-wiredep": "^1.2.0",
62
- "main-bower-files": "^2.13.1",
63
- "merge-stream": "^1.0.1",
64
- "sass": "^1.38.2"
31
+ "browser-sync": "2.27.10",
32
+ "cssnano": "5.1.14",
33
+ "delete-empty": "2.0.0",
34
+ "get-gulp-args": "0.0.1",
35
+ "gulp": "4.0.2",
36
+ "gulp-about": "1.1.0",
37
+ "gulp-add-files": "1.0.0",
38
+ "gulp-angular-filesort": "1.2.1",
39
+ "gulp-angular-templatecache": "3.0.1",
40
+ "gulp-clean": "0.4.0",
41
+ "gulp-cssimport": "7.0.0",
42
+ "gulp-filter": "7.0.0",
43
+ "gulp-htmlmin": "5.0.1",
44
+ "gulp-imagemin": "7.1.0",
45
+ "gulp-inject": "5.0.5",
46
+ "gulp-inject-string": "1.1.2",
47
+ "gulp-jsonmin": "1.2.0",
48
+ "gulp-less": "5.0.0",
49
+ "gulp-load-plugins": "2.0.8",
50
+ "gulp-ng-annotate": "2.1.0",
51
+ "gulp-notify": "4.0.0",
52
+ "gulp-postcss": "9.0.1",
53
+ "gulp-pug": "5.0.0",
54
+ "gulp-rebase-css-urls": "0.0.2",
55
+ "gulp-rename": "2.0.0",
56
+ "gulp-rev": "9.0.0",
57
+ "gulp-rev-delete-original": "0.2.3",
58
+ "gulp-rev-replace": "0.4.4",
59
+ "gulp-sass": "5.1.0",
60
+ "gulp-size": "4.0.1",
61
+ "gulp-terser": "2.1.0",
62
+ "gulp-useref": "5.0.0",
63
+ "gulp-wiredep": "1.2.0",
64
+ "hidefile": "3.0.0",
65
+ "main-bower-files": "2.13.3",
66
+ "sass": "1.56.1"
65
67
  }
66
68
  }