Skip to content

Commit 436737d

Browse files
author
Joel Mitchell
committed
Updated build process
1 parent a46b5e4 commit 436737d

File tree

10 files changed

+7091
-115
lines changed

10 files changed

+7091
-115
lines changed

src/Cofoundry.Plugins.ErrorLogging.Admin/Build/Gruntfile.js

Lines changed: 0 additions & 90 deletions
This file was deleted.

src/Cofoundry.Plugins.ErrorLogging.Admin/Build/package.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/Cofoundry.Plugins.ErrorLogging.Admin/Cofoundry.Plugins.ErrorLogging.Admin.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
</ItemGroup>
2424

2525
<ItemGroup>
26-
<Compile Remove="Build\node_modules\**" />
27-
<EmbeddedResource Remove="Build\node_modules\**" />
28-
<None Remove="Build\node_modules\**" />
26+
<Compile Remove="**\node_modules\**" />
27+
<EmbeddedResource Remove="**\node_modules\**" />
28+
<None Remove="**\node_modules\**" />
2929
</ItemGroup>
3030

3131
<ItemGroup>
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
const gulp = require('gulp');
2+
const sass = require('gulp-sass');
3+
const postcss = require('gulp-postcss');
4+
const cssnano = require('cssnano');
5+
const sassGlob = require('gulp-sass-glob');
6+
const concat = require('gulp-concat-util');
7+
const uglify = require('gulp-uglify');
8+
const path = require('path');
9+
const gulpif = require('gulp-if');
10+
const branch = require('branch-pipe')
11+
12+
exports.CofoundryBuild = class {
13+
14+
/**
15+
* Attaches several gulp tasks to an object, which includes a 'build' and
16+
* 'watch' task, as well as separate 'buildCss' and 'buildJs' tasks.
17+
*
18+
* @param {string} filePath - The base path to your admin modules, relative to the gulp script.
19+
* @param {object} config - A configuration object containing properties for the js and sass modules to build
20+
*/
21+
constructor(filePath, config) {
22+
this.filePath = filePath;
23+
this.urlBase = config.urlBase;
24+
this.jsModules = mapJsModules(config.jsModules);
25+
this.sassModules = config.sassModules || [];
26+
}
27+
28+
/**
29+
* Attaches several gulp tasks to an object, which includes a 'build' and
30+
* 'watch' task, as well as separate 'buildCss' and 'buildJs' tasks.
31+
*
32+
* @param {object} attachTo - An object to attach gulp tasks to
33+
*/
34+
addGulpTasks = function(attachTo) {
35+
let filePath = this.filePath;
36+
let urlBase = this.urlBase;
37+
let cssTasks = createSassTasks(this.sassModules);
38+
let jsTasks = createJsTasks(this.jsModules);
39+
let htmlTasks = createHtmlTasks(this.jsModules);
40+
41+
attachTo.buildCss = cssTasks ? cssTasks : noTasks;
42+
43+
var jsBuildTasks = [jsTasks, htmlTasks].filter(t => t != null);
44+
attachTo.buildJs = jsTasks.length ? gulp.parallel(jsBuildTasks) : noTasks;
45+
46+
var allBuildTasks = [cssTasks, jsTasks, htmlTasks].filter(t => t != null);
47+
attachTo.build = attachTo.default = allBuildTasks.length ? gulp.parallel(...allBuildTasks) : noTasks;
48+
49+
attachTo.watch = watch.bind(this);
50+
51+
/* PRIVATE */
52+
53+
function noTasks() {
54+
console.log('No modules found to build.');
55+
}
56+
57+
function createJsTasks(jsModules) {
58+
59+
if (!jsModules || !jsModules.length) return null;
60+
61+
var tasks = jsModules.map(module => {
62+
return jsModuleTask.bind(null, module);
63+
});
64+
65+
return gulp.parallel(...tasks);
66+
}
67+
68+
function createHtmlTasks(jsModules) {
69+
70+
if (!jsModules || !jsModules.length) return null;
71+
72+
var tasks = jsModules.filter(module => {
73+
// if we're ignoring defaults, assume there's no html templates
74+
return !module.ignoreDefaultSources;
75+
}).map(module => {
76+
return htmlModuleTask.bind(null, module);
77+
});
78+
79+
return gulp.parallel(...tasks);
80+
}
81+
82+
function createSassTasks(sassModules) {
83+
84+
if (!sassModules || !sassModules.length) return null;
85+
86+
var tasks = sassModules.map(module => {
87+
return sassModuleTask.bind(null, module.moduleName);
88+
});
89+
90+
return gulp.parallel(...tasks);
91+
}
92+
93+
function sassModuleTask(moduleName) {
94+
// moduleName is the directory e.g. "CustomEntities", which is lowercased
95+
// to make the output file name e.g. "customentities.css"
96+
let outputFileName = moduleName.toLowerCase();
97+
98+
return gulp.src(sourcePath(moduleName + '/Sass/' + outputFileName + '.scss'))
99+
.pipe(sassGlob())
100+
.pipe(sass().on('error', sass.logError))
101+
.pipe(concat(outputFileName + '.css'))
102+
.pipe(gulp.dest(sourcePath(moduleName + '/Content/css')))
103+
.pipe(postcss([cssnano()]))
104+
.pipe(concat(outputFileName + '_min.css'))
105+
.pipe(gulp.dest(sourcePath(moduleName + '/Content/css')))
106+
;
107+
}
108+
109+
function jsModuleTask(module) {
110+
111+
return gulp
112+
.src([
113+
...module.additionalSources.map(sourcePath),
114+
...module.defaultSources.map(sourcePath)
115+
])
116+
.pipe(branch.obj(src => [
117+
src.pipe(concat(module.outputFileName + '.js'))
118+
.pipe(gulp.dest(sourcePath(module.moduleName + '/Content/js'))),
119+
src.pipe(gulpif('!**/*.min.js', uglify()))
120+
.pipe(concat(module.outputFileName + '_min.js'))
121+
.pipe(gulp.dest(sourcePath(module.moduleName + '/Content/js')))
122+
]));
123+
}
124+
125+
/**
126+
* Angular html templates are bundled into a single file per module
127+
* and loaded into the app ahead of time to speed up loading.
128+
*
129+
* @param {string} moduleName The name of the module (container directory) e.g. "CustomEntities"
130+
*/
131+
function htmlModuleTask(module) {
132+
let jsModuleName = camelize(module.moduleName);
133+
134+
return gulp.src(sourcePath(module.moduleName + '/Js/**/*.html'))
135+
.pipe(concat(module.outputFileName + '_templates.js', {
136+
process: prepareTemplate
137+
}))
138+
.pipe(concat.header("angular.module('cms." + jsModuleName + "').run(['$templateCache',function(t){"))
139+
.pipe(concat.footer('}]);'))
140+
.pipe(gulp.dest(sourcePath(module.moduleName + '/Content/js')))
141+
;
142+
143+
function prepareTemplate(src, filePath) {
144+
145+
var removeSpaces = src.replace(/[\t\n\r]/gm, "");
146+
var escapeQuotes = removeSpaces.replace(/'/g, "\\'");
147+
var releativePath = path.relative(__dirname, filePath).replace(/\\/g, '/');
148+
var splitPath = releativePath.split('..');
149+
var formattedSrc = "t.put('" + (urlBase || '') + splitPath[1] + "','" + escapeQuotes + "');";
150+
151+
return formattedSrc;
152+
}
153+
}
154+
155+
function watch() {
156+
157+
this.sassModules.forEach(module => {
158+
watchSassModule(module.moduleName, module.directory);
159+
});
160+
161+
this.jsModules.forEach(module => {
162+
watchJsModule(module);
163+
watchHtmlModule(module);
164+
});
165+
}
166+
167+
function watchSassModule(moduleName, moduleDirectory) {
168+
// Currently we watch for sass and css files, but we
169+
// might also need to add images in here if they form
170+
// part of the build
171+
const EXTENSIONS = ['.css'];
172+
moduleDirectory = moduleDirectory || moduleName;
173+
174+
gulp.watch(
175+
[
176+
...globExtensions(moduleDirectory + '/Sass/**/*', EXTENSIONS),
177+
sourcePath(moduleName + '/**/*.scss')
178+
],
179+
sassModuleTask.bind(null, moduleName)
180+
);
181+
}
182+
183+
function watchJsModule(module) {
184+
gulp.watch(
185+
sourcePath(module.moduleName + '/Js/**/*.js'),
186+
jsModuleTask.bind(null, module)
187+
);
188+
}
189+
190+
function watchHtmlModule(module) {
191+
gulp.watch(
192+
sourcePath(module.moduleName + '/Js/**/*.html'),
193+
htmlModuleTask.bind(null, module)
194+
);
195+
}
196+
197+
function globExtensions(path, extensions) {
198+
var paths = [];
199+
extensions.forEach(e => {
200+
paths.push(sourcePath(path + e));
201+
});
202+
203+
return paths;
204+
}
205+
206+
function sourcePath(path) {
207+
return filePath + path;
208+
}
209+
}
210+
}
211+
212+
function mapJsModules(jsModules) {
213+
214+
return jsModules.map(mapJsModule || []);
215+
216+
function mapJsModule(module) {
217+
// If passing a string, it will be the module name (container
218+
// directory) e.g. "CustomEntities"
219+
if (typeof(module) === 'string') {
220+
module = {
221+
moduleName: module
222+
};
223+
}
224+
225+
// The standard module sources to scan for, which can be
226+
// ignored with the ignoreDefaultSources flag if you want to load
227+
// custom scripts
228+
module.defaultSources = module.ignoreDefaultSources ? [] : [
229+
module.moduleName + '/Js/Bootstrap/**/*.js',
230+
module.moduleName + '/Js/DataServices/**/*.js',
231+
module.moduleName + '/Js/Utilities/**/*.js',
232+
module.moduleName + '/Js/Filters/**/*.js',
233+
module.moduleName + '/Js/Framework/**/*.js',
234+
module.moduleName + '/Js/UIComponents/**/*.js',
235+
module.moduleName + '/Js/UIComponents/**/*.js',
236+
module.moduleName + '/Js/Routes/**/*.js',
237+
];
238+
239+
// Additonal sources allows you to load any extra libs or custom files
240+
// ahead of the standard modules.
241+
module.additionalSources = module.additionalSources || [];
242+
243+
// By default the module name is lowercased to make the output file
244+
// name e.g. "customentities.css", but you can provide a custom one
245+
module.outputFileName = module.outputFileName || module.moduleName.toLowerCase();
246+
247+
return module;
248+
}
249+
}
250+
251+
function camelize(string) {
252+
return string.charAt(0).toLowerCase() + string.slice(1);
253+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const { CofoundryBuild } = require('./CofoundryBuild');
2+
3+
// The JavaScript modules to include in the build.
4+
// Standard modules just need to provide the module name (container directory)
5+
let jsModules = ['Errors'];
6+
7+
// The Sass modules to include in the build.
8+
let sassModules = [];
9+
10+
var cofoundryBuild = new CofoundryBuild('../Modules/', {
11+
urlBase: '/Plugins/Admin',
12+
jsModules: jsModules,
13+
sassModules: sassModules
14+
})
15+
16+
// Adds tasks: buildCss, buildJs, build, watch
17+
cofoundryBuild.addGulpTasks(exports);

0 commit comments

Comments
 (0)