Last active 1 month ago

Revision 99744fb9f3a187e74b2923d0b1efc055940ab0a9

jade-watcher.js Raw
1import chokidar from 'chokidar';
2import fs from 'fs'
3import fse from 'fs-extra';
4import jade from 'jade';
5import klaw from 'klaw';
6import beautify from 'beautify';
7import cleaner from 'clean-html';
8import fg from 'fast-glob';
9import inliner from '@css-inline/css-inline';
10
11// ====================================================================
12// |
13// ====================================================================
14function log(message) {
15 const options = {
16 encoding: "utf-8",
17 flag: "a+",
18 };
19 const datetime = new Date().toISOString()
20 message = `[${datetime}] ${message}\n`
21 fse.outputFileSync('/logs/builder/jade.log', message, options);
22 console.log(message)
23}
24
25// ====================================================================
26// |
27// ====================================================================
28function compile(path) {
29
30 log(`${path} was changed`)
31
32 // Do not compile inside .delete folders
33 if (path.includes(".delete")) {
34 return
35 }
36
37 // Do not compile inside _partials folders
38 if (path.includes("layouts")) {
39 log("Recompiling /app/views/layouts")
40 compileAll('/app/views/layouts/**/*.jade')
41 return
42 }
43
44 // Do not compile inside _partials folders
45 if (path.includes("_partials") || path.includes("partials")) {
46 log("Recompiling /app/views")
47 compileAll('/app/views/**/*.jade')
48 return
49 }
50
51 // Do not compile partials (begins with _)
52 const filename = path.split("/").slice(-1).toString()
53 if (filename.startsWith("_")) {
54 const underscorecount = (filename.match(/_/g) || []).length;
55 const directoryIndex = 0 - underscorecount
56 const parentDirectory = path.split("/").slice(0,directoryIndex).join("/")+'/**/*.jade'
57 log("Recompiling "+parentDirectory)
58 compileAll( parentDirectory )
59 return
60 }
61
62 // Do not compile if the file does not end with .jade
63 if (!path.endsWith(".jade")) {
64 return
65 }
66
67 log(` Recompiling ${path}`)
68 const options = {
69 basedir: '/app/views'
70 }
71 var result = '';
72 result = jade.renderFile(path,options);
73
74 var publicPath = path
75 publicPath = publicPath.replace('/app/views','/www')
76 publicPath = publicPath.replace('.jade','.html')
77
78 // Convert to CSS Inline for Email Templates
79 // if (publicPath.includes("/www/emails")) {
80 // console.log('Inlining Email Template CSS')
81 // result = inliner.inline(result);
82 // console.log('Inlining Email Template CSS Done');
83 // }
84
85 //-
86 //- Clean HTML Section. Could cause more harm then good. Disabled for now
87 //-
88 // try {
89 // cleaner.clean(result, output => {
90 // fse.outputFileSync(publicPath, output);
91 // });
92 // } catch (err) {
93 // try {
94 // var pretty_options = {format: 'html'}
95 // fse.outputFileSync(publicPath, beautify(result, pretty_options));
96 // } catch (err) {
97 // fse.outputFileSync(publicPath, result);
98 // log(`[ERROR] HTML Cleaner: ${path}`)
99 // log(err)
100 // log(`[ERROR] Unformatted jade file was saved`)
101 // }
102 // }
103 fse.outputFileSync(publicPath, result);
104}
105
106// ====================================================================
107// |
108// ====================================================================
109function compileParents(path) {
110
111 // Do not compile inside .delete folders
112 if (path.includes(".delete")) {
113 return
114 }
115
116 // Do not compile partials (begins with _)
117 const filename = path.split("/").slice(-1).toString()
118 if (filename.startsWith("_")) {
119 return
120 }
121
122 // Do not compile inside _partials folders
123 if (path.includes("_partials") || path.includes("partials")) {
124 return
125 }
126
127 // Do not compile if the file does not end with .jade
128 if (!path.endsWith(".jade")) {
129 return
130 }
131
132 // log(` Recompiling ${path}`)
133 const options = {
134 basedir: '/app/views'
135 }
136 var result = '';
137 result = jade.renderFile(path, options);
138
139 var publicPath = path
140 publicPath = publicPath.replace('/app/views','/www')
141 publicPath = publicPath.replace('.jade','.html')
142
143 // Convert to CSS Inline for Email Templates
144 // if (publicPath.includes("/www/emails")) {
145 // console.log('Inlining Email Template CSS')
146 // result = inliner.inline(result);
147 // console.log('Inlining Email Template CSS Done');
148 // }
149
150 //-
151 //- Clean HTML Section. Could cause more harm then good. Disabled for now
152 //-
153 // try {
154 // cleaner.clean(result, output => {
155 // fse.outputFileSync(publicPath, output);
156 // });
157 // } catch (err) {
158 // try {
159 // var pretty_options = {format: 'html'}
160 // fse.outputFileSync(publicPath, beautify(result, pretty_options));
161 // } catch (err) {
162 // fse.outputFileSync(publicPath, result);
163 // log(`[ERROR] HTML Cleaner: ${path}`)
164 // log(err)
165 // log(`[ERROR] Unformatted jade file was saved`)
166 // }
167 // }
168 fse.outputFileSync(publicPath, result);
169
170}
171
172// ====================================================================
173// |
174// ====================================================================
175function compileAll(glob) {
176 return new Promise((resolve, reject) => {
177 const jadeFiles = fg.globSync(glob)
178 for (const file of jadeFiles) {
179 compileParents(file);
180 }
181 });
182}
183
184// ====================================================================
185// |
186// ====================================================================
187function startWatcher() {
188 const watchFolders = [
189 '/app/views/**/*.jade',
190 ]
191
192 // https://github.com/paulmillr/chokidar
193 const options = {
194 awaitFinish: true,
195 ignoreInitial: true,
196 usePolling: true,
197 interval: 100
198 }
199
200 const watcher = chokidar.watch(watchFolders, options).on('all', (event, path) => {
201 });
202
203 watcher
204 .on('add', path => compile(path))
205 .on('change', path => compile(path))
206 .on('unlink', path => compile(path));
207
208 watcher
209 .on('ready', () => log('********** Watch is running **********'));
210}
211
212// ====================================================================
213// | MAIN
214// ====================================================================
215async function go() {
216 if (process.argv[2] == 'compile-and-watch') {
217 await compileAll('/app/views/**/*.jade');
218 startWatcher();
219 } else if(process.argv[2] == 'compile-only') {
220 await compileAll('/app/views/**/*.jade');
221 } else {
222 startWatcher();
223 }
224}
225
226go()
javascript-watcher.js Raw
1import chokidar from 'chokidar';
2import fs from 'fs'
3import fse from 'fs-extra';
4import path from 'path';
5import fg from 'fast-glob';
6
7// ====================================================================
8// |
9// ====================================================================
10function log(message) {
11 const options = {
12 encoding: "utf-8",
13 flag: "a+",
14 };
15 const datetime = new Date().toISOString()
16 message = `[${datetime}] ${message}\n`
17 fse.outputFileSync('/logs/builder/javascript.log', message, options);
18 console.log(message)
19}
20
21// ====================================================================
22// |
23// ====================================================================
24function concatJavascript(path) {
25 log('-----------------------');
26 log(path);
27
28 var publicPath = path
29 publicPath = publicPath.replace('/app/js','/www/js')
30
31 var jsFolder = path;
32 jsFolder = jsFolder.split("/")[3];
33
34 const source = `/app/js/${jsFolder}`
35 const destination = `/www/js/${jsFolder}.js`
36 fs.readdir(source, (err, files) => {
37 if (err) throw err;
38
39 fse.ensureFileSync(destination)
40 fs.writeFileSync(destination,'')
41 var sortedfiles = files.sort()
42 sortedfiles.forEach(file => {
43 const filePath = `${source}/${file}`
44 var contents = fs.readFileSync(filePath);
45 const spacer = `\n// ====================================================================\n// |\n// |\n// | ${file}\n// |\n// |\n// ====================================================================\n`
46 fs.appendFileSync(destination, spacer+contents)
47 });
48 });
49
50}
51
52// ====================================================================
53// |
54// ====================================================================
55function compileAll(glob) {
56 return new Promise((resolve, reject) => {
57 const javascriptFiles = fg.globSync(glob)
58 for (const file of javascriptFiles) {
59 concatJavascript(file);
60 }
61 log(`Done`)
62 });
63}
64
65// ====================================================================
66// |
67// ====================================================================
68function startWatcher(watchFolders) {
69
70 // https://github.com/paulmillr/chokidar
71 const options = {
72 awaitFinish: true,
73 ignoreInitial: true,
74 usePolling: true,
75 interval: 100
76 }
77
78 const watcher = chokidar.watch(watchFolders, options).on('all', (event, path) => {
79 log(event, path);
80 });
81
82 watcher
83 .on('add', path => concatJavascript(path))
84 .on('change', path => concatJavascript(path))
85 .on('unlink', path => concatJavascript(path));
86
87 watcher
88 .on('ready', () => log('********** Watch is running **********'));
89
90}
91
92// ====================================================================
93// | MAIN
94// ====================================================================
95async function go() {
96 const watchFolders = [
97 '/app/js'
98 ]
99 if (process.argv[2] == 'compile-and-watch') {
100 await compileAll('/app/js/*/**.js')
101 startWatcher(watchFolders);
102 } else if(process.argv[2] == 'compile-only') {
103 await compileAll('/app/js/*/**.js')
104 } else {
105 startWatcher(watchFolders);
106 }
107}
108
109go()
package.json Raw
1{
2 "name": "workflowmasters-builder",
3 "type": "module",
4 "devDependencies": {
5 "beautify": "0.0.8",
6 "chokidar": "3.6.0",
7 "character-parser": "4.0.0",
8 "clean-html": "2.0.1",
9 "concat-files": "0.1.1",
10 "fast-glob": "3.3.1",
11 "fs-extra": "11.1.1",
12 "glob": "10.3.10",
13 "html-prettify": "1.0.7",
14 "jade": "1.11.0",
15 "klaw": "4.1.0",
16 "pug": "3.0.2",
17 "sass": "1.64.1",
18 "through2": "4.0.2",
19 "@css-inline/css-inline":"0.14.1",
20 "watcher": "2.2.2"
21 },
22 "scripts": {
23 "watch": "./watcher.js",
24 "test": "gulp test"
25 }
26}
sass-watcher.js Raw
1import chokidar from 'chokidar';
2import fs from 'fs'
3import fse from 'fs-extra';
4import * as sass from 'sass';
5import fg from 'fast-glob';
6
7// ====================================================================
8// |
9// ====================================================================
10function log(message) {
11 const options = {
12 encoding: "utf-8",
13 flag: "a+",
14 };
15 const datetime = new Date().toISOString()
16 message = `[${datetime}] ${message}\n`
17 fse.outputFileSync('/logs/builder/sass.log', message, options);
18 console.log(message)
19}
20
21// ====================================================================
22// |
23// ====================================================================
24function compile(path) {
25 log('-----------------------');
26
27 // Do not compile inside .delete folders
28 if (path.includes(".delete")) {
29 return
30 }
31
32 const filename = path.split("/").slice(-1).toString()
33 if (filename.startsWith("_")) {
34 compileAll()
35 return
36 }
37
38 const options = {
39 logger: {
40 warn(message, options) {
41 if (options.span) {
42 log('====================================================================================================================')
43 log(`Warning when compiling: ${options.span.url.pathname}:`)
44 log(` ${message}\n`)
45 }
46 },
47 debug(message, options) {
48 if (options.span) {
49 log('====================================================================================================================')
50 log(`Debug message compiling: ${options.span.url.pathname}:`)
51 log(` ${message}\n`)
52 }
53 }
54 }
55 }
56
57 try {
58 const result = sass.compile(path, options);
59 var publicPath = path
60 publicPath = publicPath.replace('/app/scss','/www/css')
61 publicPath = publicPath.replace('.scss','.css')
62 fse.outputFileSync(publicPath, result.css);
63 } catch (err) {
64 log(`[ERROR] SASS Compile: ${path}`)
65 log(err)
66 }
67
68}
69
70// ====================================================================
71// |
72// ====================================================================
73function compileParents(path) {
74
75 // Do not compile inside .delete folders
76 if (path.includes(".delete")) {
77 return
78 }
79
80 // Do not compile partials (begins with _)
81 const filename = path.split("/").slice(-1).toString()
82 if (filename.startsWith("_")) {
83 return
84 }
85
86 // Do not compile if the file does not end with .scss
87 if (!path.endsWith(".scss")) {
88 return
89 }
90
91 const options = {
92 logger: {
93 warn(message, options) {
94 if (options.span) {
95 log('=============================')
96 log(`Warning when compiling: ${options.span.url.pathname}:`)
97 log(` ${message}\n`)
98 }
99 },
100 debug(message, options) {
101 if (options.span) {
102 log('=============================')
103 log(`Debug message compiling: ${options.span.url.pathname}:`)
104 log(` ${message}\n`)
105 }
106 }
107 }
108 }
109
110 try {
111 const result = sass.compile(path, options);
112 var publicPath = path
113 publicPath = publicPath.replace('/app/scss','/www/css')
114 publicPath = publicPath.replace('.scss','.css')
115 fse.outputFileSync(publicPath, result.css);
116 } catch (err) {
117 log(`[ERROR] SASS Compile: ${path}`)
118 log(err)
119 }
120
121
122}
123
124// ====================================================================
125// |
126// ====================================================================
127function compileAll(glob) {
128 return new Promise((resolve, reject) => {
129 const sassFiles = fg.globSync(glob)
130 for (const file of sassFiles) {
131 compileParents(file);
132 }
133 log(`Done`)
134 });
135}
136
137// ====================================================================
138// |
139// ====================================================================
140function startWatcher(watchFolders) {
141
142 // https://github.com/paulmillr/chokidar
143 const options = {
144 awaitFinish: true,
145 ignoreInitial: true,
146 usePolling: true,
147 interval: 100
148 }
149
150 const watcher = chokidar.watch(watchFolders, options).on('all', (event, path) => {
151 log(`${path} was ${event}`);
152 });
153
154 watcher
155 .on('add', path => compile(path))
156 .on('change', path => compile(path))
157 .on('unlink', path => compile(path));
158
159 watcher
160 .on('ready', () => log('********** Watch is running **********'));
161
162}
163
164// ====================================================================
165// | MAIN
166// ====================================================================
167async function go() {
168 const watchFolders = [
169 '/app/scss/**/*.scss'
170 ]
171 if (process.argv[2] == 'compile-and-watch') {
172 await compileAll('/app/scss/**/*.scss')
173 startWatcher(watchFolders);
174 } else if(process.argv[2] == 'compile-only') {
175 await compileAll('/app/scss/**/*.scss')
176 } else {
177 startWatcher(watchFolders);
178 }
179}
180
181go()