add return to core/header (#2995)
[openemr.git] / gulpfile.js
blobf902c5c908a1df44b91cfcf05007a573d1b2095a
1 'use strict';
3 // modules
4 const browserSync = require('browser-sync');
5 const csso = require('gulp-csso');
6 const del = require('del');
7 const fs = require('fs');
8 const glob = require('glob');
9 const gap = require('gulp-append-prepend');
10 const replace = require('replace-in-file');
11 const gulp = require('gulp');
12 const argv = require('minimist')(process.argv.slice(2));
13 const gulpif = require('gulp-if');
14 const prefix = require('gulp-autoprefixer');
15 const reload = browserSync.reload;
16 const rename = require('gulp-rename');
17 const sass = require('gulp-sass');
18 const sourcemaps = require('gulp-sourcemaps');
19 const gulp_watch = require('gulp-watch');
21 // package.json
22 const packages = require('./package.json');
24 // configuration
25 let config = {
26     all: [], // must always be empty
28     // Command Line Arguments
29     dev: argv['dev'],
30     build: argv['b'],
31     syncOnly: argv['sync-only'],
32     proxy: argv['p'],
33     install: argv['i'],
35     // Source file locations
36     src: {
37         styles: {
38             style_portal: 'interface/themes/patientportal-style.scss',
39             style_uni: 'interface/themes/oe-styles/style_*.scss',
40             style_color: 'interface/themes/colors/*.scss',
41             directional: 'interface/themes/directional.scss'
42         }
43     },
44     dist: {
45         assets: 'public/assets/'
46     },
47     dest: {
48         themes: 'public/themes'
49     }
52 // Clean up lingering static themes
53 function clean(done) {
54     del.sync([config.dest.themes + "/*"]);
55     done();
58 // Parses command line arguments
59 function ingest(done) {
60     if (config.dev && typeof config.dev !== "boolean") {
61         // allows for custom proxy to be passed into script
62         config.proxy = config.dev;
63         config.dev = true;
64     }
65     done();
68 // definition of header for all compiled css
69 const autoGeneratedHeader = `
70 /*! This style sheet was autogenerated using gulp + scss
71  *  For usage instructions, see: https://github.com/openemr/openemr/blob/master/interface/README.md
72  */
75 // standard themes css compilation
76 function styles_style_portal() {
77     return gulp.src(config.src.styles.style_portal)
78     .pipe(sourcemaps.init())
79     .pipe(sass().on('error', sass.logError))
80     .pipe(prefix('last 1 version'))
81     .pipe(gap.prependText(autoGeneratedHeader))
82     .pipe(gulpif(!config.dev, csso()))
83     .pipe(gulpif(!config.dev, sourcemaps.write()))
84     .pipe(gulp.dest(config.dest.themes))
85     .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
86     .pipe(gulpif(config.dev, reload({ stream: true })));
88 // standard themes css compilation
89 function styles_style_uni() {
90     return gulp.src(config.src.styles.style_uni)
91         .pipe(sourcemaps.init())
92         .pipe(sass().on('error', sass.logError))
93         .pipe(prefix('last 1 version'))
94         .pipe(gap.prependText(autoGeneratedHeader))
95         .pipe(gulpif(!config.dev, csso()))
96         .pipe(gulpif(!config.dev, sourcemaps.write()))
97         .pipe(gulp.dest(config.dest.themes))
98         .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
99         .pipe(gulpif(config.dev, reload({ stream: true })));
102 // color themes css compilation
103 function styles_style_color() {
104     return gulp.src(config.src.styles.style_color)
105         .pipe(sourcemaps.init())
106         .pipe(sass().on('error', sass.logError))
107         .pipe(prefix('last 1 version'))
108         .pipe(gap.prependText(autoGeneratedHeader))
109         .pipe(gulpif(!config.dev, csso()))
110         .pipe(gulpif(!config.dev, sourcemaps.write()))
111         .pipe(gulp.dest(config.dest.themes))
112         .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
113         .pipe(gulpif(config.dev, reload({ stream: true })));
116 // rtl standard themes css compilation
117 function rtl_style_portal() {
118     return gulp.src(config.src.styles.style_portal)
119         .pipe(gap.prependText('$dir: rtl;\n@import "rtl";\n@import "directional";\n')) // watch out for this relative path!
120         .pipe(gap.appendText('@include if-rtl { @include rtl_style; }\n'))
121         .pipe(sourcemaps.init())
122         .pipe(sass().on('error', sass.logError))
123         .pipe(prefix('last 1 version'))
124         .pipe(gap.prependText(autoGeneratedHeader))
125         .pipe(gulpif(!config.dev, csso()))
126         .pipe(gulpif(!config.dev, sourcemaps.write()))
127         .pipe(rename({ prefix: "rtl_" }))
128         .pipe(gulp.dest(config.dest.themes))
129         .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
130         .pipe(gulpif(config.dev, reload({ stream: true })));
133 // rtl standard themes css compilation
134 function rtl_style_uni() {
135     return gulp.src(config.src.styles.style_uni)
136         .pipe(gap.prependText('$dir: rtl;\n@import "../rtl";\n')) // watch out for this relative path!
137         .pipe(gap.appendText('@include if-rtl { @include rtl_style; #bigCal { border-right: 1px solid $black !important; } }\n'))
138         .pipe(sourcemaps.init())
139         .pipe(sass().on('error', sass.logError))
140         .pipe(prefix('last 1 version'))
141         .pipe(gap.prependText(autoGeneratedHeader))
142         .pipe(gulpif(!config.dev, csso()))
143         .pipe(gulpif(!config.dev, sourcemaps.write()))
144         .pipe(rename({ prefix: "rtl_" }))
145         .pipe(gulp.dest(config.dest.themes))
146         .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
147         .pipe(gulpif(config.dev, reload({ stream: true })));
150 // rtl color themes css compilation
151 function rtl_style_color() {
152     return gulp.src(config.src.styles.style_color)
153         .pipe(gap.prependText('$dir: rtl;\n@import "../rtl";\n')) // watch out for this relative path!
154         .pipe(gap.appendText('@include if-rtl { @include rtl_style; #bigCal { border-right: 1px solid $black !important; } }\n'))
155         .pipe(sourcemaps.init())
156         .pipe(sass().on('error', sass.logError))
157         .pipe(prefix('last 1 version'))
158         .pipe(gap.prependText(autoGeneratedHeader))
159         .pipe(gulpif(!config.dev, csso()))
160         .pipe(gulpif(!config.dev, sourcemaps.write()))
161         .pipe(rename({ prefix: "rtl_" }))
162         .pipe(gulp.dest(config.dest.themes))
163         .pipe(gulpif(config.dev && config.build, gulp.dest(config.dest.themes)))
164         .pipe(gulpif(config.dev, reload({ stream: true })));
167 // compile themes
168 const styles = gulp.parallel(styles_style_uni, styles_style_portal, styles_style_color, rtl_style_portal, rtl_style_uni, rtl_style_color);
170 // Copies (and distills, if possible) assets from node_modules to public/assets
171 function install(done) {
172     // combine dependencies and napa sources into one object
173     const dependencies = packages.dependencies;
174     for (let key in packages.napa) {
175         if (packages.napa.hasOwnProperty(key)) {
176             dependencies[key] = packages.napa[key];
177         }
178     }
180     for (let key in dependencies) {
181         // check if the property/key is defined in the object itself, not in parent
182         if (dependencies.hasOwnProperty(key)) {
183             if (key == 'dwv') {
184                 // dwv is special and need to copy dist, decoders and locales
185                 gulp.src('node_modules/' + key + '/dist/**/*')
186                     .pipe(gulp.dest(config.dist.assets + key + '/dist'));
187                 gulp.src('node_modules/' + key + '/decoders/**/*')
188                     .pipe(gulp.dest(config.dist.assets + key + '/decoders'));
189                 gulp.src('node_modules/' + key + '/locales/**/*')
190                     .pipe(gulp.dest(config.dist.assets + key + '/locales'));
191             } else if (key == 'bootstrap' || key == 'bootstrap-v4-rtl' || key == 'bootswatch') {
192                 // bootstrap, bootstrap-v4-rtl, and bootswatch are special and need to copy dist and scss
193                 gulp.src('node_modules/' + key + '/dist/**/*')
194                     .pipe(gulp.dest(config.dist.assets + key + '/dist'));
195                 gulp.src('node_modules/' + key + '/scss/**/*')
196                     .pipe(gulp.dest(config.dist.assets + key + '/scss'));
197             } else if (key == 'select2-bootstrap4-theme') {
198                 // select2-bootstrap4-theme is special and need to copy dist and src
199                 //  modify src/layout.scss in order for sass build to work by removing:
200                 //   @import "~bootstrap/scss/functions";
201                 //   @import "~bootstrap/scss/variables";
202                 //   @import "~bootstrap/scss/mixins";
203                 gulp.src('node_modules/' + key + '/dist/**/*')
204                     .pipe(gulp.dest(config.dist.assets + key + '/dist'));
205                 gulp.src('node_modules/' + key + '/src/**/*')
206                     .pipe(gulp.dest(config.dist.assets + key + '/src'))
207                     .on('end', function() {
208                         replace({
209                             files: config.dist.assets + key + '/src/layout.scss',
210                             from:
211                                 [
212                                     /@import "~bootstrap\/scss\/functions";/,
213                                     /@import "~bootstrap\/scss\/variables";/,
214                                     /@import "~bootstrap\/scss\/mixins";/
215                                 ],
216                             to: '',
217                         });
218                     });
219             } else if (fs.existsSync('node_modules/' + key + '/dist')) {
220                 // only copy dist directory, if it exists
221                 gulp.src('node_modules/' + key + '/dist/**/*')
222                     .pipe(gulp.dest(config.dist.assets + key + '/dist'));
223             } else {
224                 // copy everything
225                 gulp.src('node_modules/' + key + '/**/*')
226                     .pipe(gulp.dest(config.dist.assets + key));
227             }
228         }
229     }
231     done();
234 function watch() {
235     // watch all changes and re-run styles
236     gulp.watch('./interface/**/*.scss', { interval: 1000, mode: 'poll' }, styles);
238     // watch all changes to css/php files in themes and copy to public
239     return gulp_watch('./interface/themes/*.{css,php}', { ignoreInitial: false })
240         .pipe(gulp.dest(config.dest.themes));
243 function sync_only(done) {
244     browserSync.init({
245         proxy: "127.0.0.1:" + config.proxy,
246         open: false
247     });
248     done();
251 // Will start browser sync and/or watch changes to scss
252 //  = Runs task(styles) first
253 function sync() {
254     if (config.proxy) {
255         browserSync.init({
256             proxy: "127.0.0.1:" + config.proxy
257         });
258     }
260     // copy all leftover root-level components to the theme directory
261     // hoping this is only temporary
262     return gulp.src(['interface/themes/*.{css,php}'])
263         .pipe(gulp.dest(config.dest.themes));
266 // Export watch task
267 exports.watch = watch;
269 // Export pertinent default task
270 // - Note that the default task runs if no other task is chosen,
271 //    which is generally how this script is always used (except in
272 //    rare case where the user is running the watch task).
273 if (config.install) {
274     exports.default = gulp.series(install)
275 } else if (config.syncOnly && config.proxy) {
276     exports.default = gulp.parallel(sync_only, watch)
277 } else {
278     exports.default = gulp.series(clean, ingest, styles, sync);