mod-build 3.7.1 → 3.7.2-7.beta-5
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/CHANGELOG.md +96 -0
- package/gulp-tasks/build.js +4 -4
- package/gulp-tasks/get-default-trade-questions.js +155 -0
- package/gulp-tasks/grab-cdn.js +26 -21
- package/gulp-tasks/grab-mhsadmin-data.js +418 -0
- package/gulp-tasks/grab-section-deals-components.js +47 -0
- package/gulp-tasks/grab-shared-scripts.js +21 -5
- package/gulp-tasks/serve.js +5 -5
- package/gulp-tasks/tasks.js +36 -3
- package/gulp-tasks/templates.js +95 -12
- package/package.json +1 -1
- package/src/scripts/vendor/heap-addeventproperties-identify.js +1 -1
- package/src/scripts/vendor/heap-tracking.js +1 -1
- package/src/scripts/vendor/heap-vwo.js +1 -1
- package/src/scripts/vendor/visual-website-optimizer.js +7 -8
- package/src/templates/_partials/scripts/vwo-redirect-callback.html +20 -0
- package/src/trade-questions/alerts_medical.js +111 -0
- package/src/trade-questions/bathroom_refacing.js +96 -0
- package/src/trade-questions/cabinet_refacing.js +251 -0
- package/src/trade-questions/cabinets.js +35 -0
- package/src/trade-questions/concrete_foundation.js +57 -0
- package/src/trade-questions/door.js +143 -0
- package/src/trade-questions/flooring.js +185 -0
- package/src/trade-questions/garage_door.js +89 -0
- package/src/trade-questions/gutters.js +45 -0
- package/src/trade-questions/home_security.js +130 -0
- package/src/trade-questions/home_warranty.js +57 -0
- package/src/trade-questions/hot_tubs.js +92 -0
- package/src/trade-questions/hvac.js +179 -0
- package/src/trade-questions/index.js +26 -0
- package/src/trade-questions/insulation.js +118 -0
- package/src/trade-questions/plumbing.js +260 -0
- package/src/trade-questions/roofing.js +118 -0
- package/src/trade-questions/siding.js +150 -0
- package/src/trade-questions/solar.js +69 -0
- package/src/trade-questions/stair_lifts.js +47 -0
- package/src/trade-questions/tree_services.js +169 -0
- package/src/trade-questions/walk_in_tubs.js +47 -0
- package/src/trade-questions/water_treatment.js +48 -0
- package/src/trade-questions/windows.js +132 -0
- package/src/trade-questions-config.js +139 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/* globals Promise */
|
|
2
|
+
/* eslint-disable space-before-function-paren */
|
|
3
|
+
const request = require('request');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
|
|
6
|
+
module.exports = function(gulp, gulpPlugins, siteSettings, siteData) {
|
|
7
|
+
const lastModDateOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };
|
|
8
|
+
const tradeLookUp = [];
|
|
9
|
+
const dateLocalString = 'en-US';
|
|
10
|
+
const showCostCalFor = ['windows', 'hvac'];
|
|
11
|
+
const perPageArticlesLimit = 100;
|
|
12
|
+
const articles = [];
|
|
13
|
+
let articleConfigsCount = 0, templatesCount = 0, cachedContractors = {};
|
|
14
|
+
|
|
15
|
+
const log = {
|
|
16
|
+
success: function(icon = '\u{23F3}', message = '') {
|
|
17
|
+
console.log(gulpPlugins.colors.bright, gulpPlugins.colors.fg.green, icon, ' ', message, gulpPlugins.colors.reset);
|
|
18
|
+
},
|
|
19
|
+
info: function(message = '') {
|
|
20
|
+
console.log(message);
|
|
21
|
+
},
|
|
22
|
+
error: function(message, throwError = true) {
|
|
23
|
+
console.log(gulpPlugins.colors.bg.red, gulpPlugins.colors.bright, message, gulpPlugins.colors.reset);
|
|
24
|
+
if (throwError) {
|
|
25
|
+
throw new Error(message);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function formatDate(date) {
|
|
31
|
+
const d = new Date(date);
|
|
32
|
+
const year = d.getFullYear();
|
|
33
|
+
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
34
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
35
|
+
return [year, month, day].join('-');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function processAndSortContractorList(list, ratingPropertyName = 'reviewScore', minRating = null) {
|
|
39
|
+
list = list.sort(function(a, b) {
|
|
40
|
+
if (a[ratingPropertyName] === null && b[ratingPropertyName] === null) {
|
|
41
|
+
return a.displayName.localeCompare(b.displayName);
|
|
42
|
+
}
|
|
43
|
+
return b[ratingPropertyName] - a[ratingPropertyName];
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (minRating) {
|
|
47
|
+
list = await list.filter(data => !data[ratingPropertyName] || data[ratingPropertyName] >= minRating);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
list = await list.map(function(data, i) {
|
|
51
|
+
if (data) {
|
|
52
|
+
data.index = i;
|
|
53
|
+
}
|
|
54
|
+
return data;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return list;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// helper function to create nested object dynamically
|
|
61
|
+
function assign(obj, keyPath, value) {
|
|
62
|
+
const lastKeyIndex = keyPath.length - 1;
|
|
63
|
+
for (var i = 0; i < lastKeyIndex; ++i) {
|
|
64
|
+
const key = keyPath[i];
|
|
65
|
+
if (!(key in obj)) {
|
|
66
|
+
obj[key] = {};
|
|
67
|
+
}
|
|
68
|
+
obj = obj[key];
|
|
69
|
+
}
|
|
70
|
+
obj[keyPath[lastKeyIndex]] = value;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const sortArticlesByDate = function(articlesList) {
|
|
74
|
+
if (articlesList.length) {
|
|
75
|
+
articlesList.sort(function(a, b) {
|
|
76
|
+
return new Date(b.data.published) - new Date(a.data.published);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// MARK: configureGlobalVariables
|
|
82
|
+
const configureGlobalVariables = function(siteData, siteSettings) {
|
|
83
|
+
return new Promise(resolve => {
|
|
84
|
+
const DOMAIN = `https://${siteSettings.nodeEnv === 'qa.modernize.com' ? 'qa' : ''}mhsadmin.wpenginepowered.com`;
|
|
85
|
+
const WP_ENDPOINT_BASE_URL = `${DOMAIN}/wp-json/wp/v2`;
|
|
86
|
+
siteSettings.endpoints = {};
|
|
87
|
+
siteSettings.endpoints.GET_DETAILED_ARTICLES = `${WP_ENDPOINT_BASE_URL}/article?_fields=data,meta,slug&per_page=${perPageArticlesLimit}&site=${siteData.siteName}`;
|
|
88
|
+
siteSettings.endpoints.GET_CONTRACTORS = `${WP_ENDPOINT_BASE_URL}/contractor`;
|
|
89
|
+
siteSettings.endpoints.GET_SITE_DETAILS = `${WP_ENDPOINT_BASE_URL}/site?_fields=data,slug,&site=${siteData.siteName}`;
|
|
90
|
+
|
|
91
|
+
siteData.sitemap = [];
|
|
92
|
+
siteData.page.articlesConfig = {
|
|
93
|
+
siteDetails: {},
|
|
94
|
+
articlesWithContractors: {},
|
|
95
|
+
tradeHubPagesArticlesList: {},
|
|
96
|
+
homePageArticlesList: {
|
|
97
|
+
featured: [],
|
|
98
|
+
top: [],
|
|
99
|
+
recent: []
|
|
100
|
+
},
|
|
101
|
+
defaultHomePage: 'home-services'
|
|
102
|
+
};
|
|
103
|
+
resolve();
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// MARK: getArticlesList
|
|
108
|
+
const getSiteDetails = async (siteData, siteSettings) => {
|
|
109
|
+
return await new Promise((resolve) => {
|
|
110
|
+
if (!siteData.page) {
|
|
111
|
+
log.error('page is not defined in siteData!');
|
|
112
|
+
}
|
|
113
|
+
const { page, sitemap } = siteData;
|
|
114
|
+
const { articlesConfig } = page;
|
|
115
|
+
const { siteDetails, defaultHomePage } = articlesConfig;
|
|
116
|
+
return request(siteSettings.endpoints.GET_SITE_DETAILS, async function(_xhr, response, body) {
|
|
117
|
+
if (response.statusCode === 200) {
|
|
118
|
+
let result = await JSON.parse(body);
|
|
119
|
+
if (result.length) {
|
|
120
|
+
result = result.filter((data) => data.slug === siteData.siteName);
|
|
121
|
+
}
|
|
122
|
+
await Object.assign(siteDetails, result[0]);
|
|
123
|
+
siteDetails.vertical = await siteDetails?.data?.homepage?.hero?.heading;
|
|
124
|
+
siteDetails.costCalculatorTheme = siteData.costCalculatorTheme ? siteData.costCalculatorTheme : siteDetails?.slug;
|
|
125
|
+
siteDetails.domain = await siteDetails?.data?.domain?.replace(/\/*?$/, '');
|
|
126
|
+
siteDetails.homepage = await siteDetails?.data?.homepage?.slug ? siteDetails?.data?.homepage?.slug : defaultHomePage;
|
|
127
|
+
siteDetails.canonicalURL = await `${siteDetails?.domain}/${siteDetails?.homepage}/`;
|
|
128
|
+
if (siteDetails?.data?.favicon && Object.keys(siteDetails.data.favicon).length) {
|
|
129
|
+
page.headConfig.faviconPath = siteDetails.data.favicon.url ? siteDetails.data.favicon.url : page.headConfig.faviconPath;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
sitemap.push(
|
|
133
|
+
{
|
|
134
|
+
link: `${siteDetails.domain}/${siteDetails.homepage}/`,
|
|
135
|
+
lastMod: formatDate(new Date().toLocaleDateString(dateLocalString, lastModDateOptions))
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
resolve();
|
|
139
|
+
} else {
|
|
140
|
+
log.error('GET_SITE_DETAILS - Something went wrong!');
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// MARK: getDetailedArticles
|
|
147
|
+
const getDetailedArticles = async (siteSettings, page = 1) => {
|
|
148
|
+
return await new Promise((resolve) => {
|
|
149
|
+
log.info(`Fetching articles from page ${page?.toString()?.padStart(2, '0')}: ${siteSettings.endpoints.GET_DETAILED_ARTICLES}&page=${page}`);
|
|
150
|
+
return request(`${siteSettings.endpoints.GET_DETAILED_ARTICLES}&page=${page}`, async function(_xhr, response, body) {
|
|
151
|
+
if (response.statusCode === 200) {
|
|
152
|
+
const wpArticleTotalPages = await parseInt(response.headers['x-wp-totalpages']);
|
|
153
|
+
await articles.push(...JSON.parse(body));
|
|
154
|
+
if (page < wpArticleTotalPages) {
|
|
155
|
+
// recursive call to get the articles from next pages
|
|
156
|
+
await getDetailedArticles(siteSettings, page + 1);
|
|
157
|
+
} else {
|
|
158
|
+
log.success('\u{2705}', `Finished Fetching article(s) from ${wpArticleTotalPages} page(s)`);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
log.error('GET_DETAILED_ARTICLES - Something went wrong!');
|
|
162
|
+
}
|
|
163
|
+
resolve();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// MARK: getContractors
|
|
169
|
+
const getContractors = async (trade, siteSettings) => {
|
|
170
|
+
if (!trade) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
return await new Promise((resolve) => {
|
|
174
|
+
if (Object.keys(cachedContractors).length && cachedContractors[trade]) {
|
|
175
|
+
resolve(cachedContractors[trade]);
|
|
176
|
+
return;
|
|
177
|
+
} else {
|
|
178
|
+
return request(`${siteSettings.endpoints.GET_CONTRACTORS}?trade=${trade}`, async function(_xhr, response, body) {
|
|
179
|
+
if (response.statusCode === 200) {
|
|
180
|
+
const result = await JSON.parse(body);
|
|
181
|
+
cachedContractors = await { ...cachedContractors, [trade]: result };
|
|
182
|
+
resolve(result);
|
|
183
|
+
} else {
|
|
184
|
+
log.error('GET_CONTRACTORS - Something went wrong!', false);
|
|
185
|
+
resolve([]);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const getZipCardMarkup = async function(trade, gulpPlugins) {
|
|
193
|
+
let zipCard = null;
|
|
194
|
+
|
|
195
|
+
const _insertTrade = function(htmlString) {
|
|
196
|
+
const markup = gulpPlugins.htmlParser.parse(htmlString);
|
|
197
|
+
markup.querySelector('.btn--zip').setAttribute('data-service', trade.slug.toLowerCase().replaceAll(/[-|\s]/ig, '_'));
|
|
198
|
+
markup.querySelector('.trade').textContent = trade.displayName;
|
|
199
|
+
return markup;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
return new Promise((resolve) => {
|
|
203
|
+
if (zipCard) {
|
|
204
|
+
zipCard = _insertTrade(zipCard);
|
|
205
|
+
return resolve(zipCard);
|
|
206
|
+
}
|
|
207
|
+
fs.readFile('./src/shared-components/section-deals/_partials/page-card-zip.html', 'utf-8', function(err, data) {
|
|
208
|
+
if (err) {
|
|
209
|
+
log.error('page-card-zip.html not found at "/src/shared-components/section-deals/_partials/page-card-zip.html" ');
|
|
210
|
+
}
|
|
211
|
+
zipCard = data;
|
|
212
|
+
zipCard = _insertTrade(zipCard);
|
|
213
|
+
resolve(zipCard);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// MARK: buildTemplates
|
|
219
|
+
async function buildTemplates(siteData, siteSettings, done) {
|
|
220
|
+
const { srcFolder, templatesSubfolder } = siteSettings;
|
|
221
|
+
const { page } = await siteData;
|
|
222
|
+
const { articlesConfig } = page;
|
|
223
|
+
const { articlesWithContractors, siteDetails } = articlesConfig;
|
|
224
|
+
const templatesPath = `${srcFolder}/${templatesSubfolder}/`;
|
|
225
|
+
return await new Promise(function(resolve) {
|
|
226
|
+
if (articlesWithContractors && Object.keys(articlesWithContractors).length) {
|
|
227
|
+
log.success('\u{23F3}', 'Building Article(s)...');
|
|
228
|
+
Object.entries(articlesWithContractors).forEach(async function([trade, articlesList]) {
|
|
229
|
+
Object.entries(articlesList).forEach(function([pageName, articleData]) {
|
|
230
|
+
let costCalculatorTrade = trade;
|
|
231
|
+
costCalculatorTrade = costCalculatorTrade.toLowerCase() === 'gutters' ? 'gutter' : costCalculatorTrade;
|
|
232
|
+
const tradeHubFileContent = `{{#page.articlesConfig.tradeHubPagesArticlesList.${trade}}}
|
|
233
|
+
{{fileInclude 'src/shared-components/section-deals/components/trade-hub-template.html'
|
|
234
|
+
tradeHubPageArticles = this
|
|
235
|
+
trade = '${articleData.data.trade.title}'
|
|
236
|
+
costCalculatorTrade = '${costCalculatorTrade}'
|
|
237
|
+
showCostCalculator = ${showCostCalFor.includes(trade)}
|
|
238
|
+
}}{{/page.articlesConfig.tradeHubPagesArticlesList.${trade}}}
|
|
239
|
+
<script>
|
|
240
|
+
window.siteData.trade='${trade}';
|
|
241
|
+
</script>`;
|
|
242
|
+
|
|
243
|
+
const fileName = articleData.slug;
|
|
244
|
+
const fileContent = `{{#page.articlesConfig.articlesWithContractors.${trade}.${pageName}}}
|
|
245
|
+
{{fileInclude 'src/shared-components/section-deals/components/article-template.html'
|
|
246
|
+
article = this
|
|
247
|
+
trade = '${trade}'
|
|
248
|
+
}}{{/page.articlesConfig.articlesWithContractors.${trade}.${pageName}}}`;
|
|
249
|
+
// make the directory by trade name
|
|
250
|
+
fs.mkdir(`${templatesPath}/${siteDetails.homepage}/${articleData.data.trade.slug}/`, { recursive: true }, async function(error) {
|
|
251
|
+
if (error) {
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
fs.writeFile(`${templatesPath}/${siteDetails.homepage}/${articleData.data.trade.slug}/index.html`, tradeHubFileContent, function(err) {
|
|
255
|
+
if (err) {
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
258
|
+
fs.writeFile(`${templatesPath}/${siteDetails.homepage}/${articleData.data.trade.slug}/${fileName}.html`, fileContent, function($err) {
|
|
259
|
+
if ($err) {
|
|
260
|
+
throw $err;
|
|
261
|
+
}
|
|
262
|
+
templatesCount++;
|
|
263
|
+
log.info(`Article template ${templatesCount?.toString()?.padStart(2, '0')}: ${templatesPath}${articleData.data.trade.slug}/${siteDetails.homepage}/${fileName}.html`);
|
|
264
|
+
if (articleConfigsCount === templatesCount) {
|
|
265
|
+
siteData.page.lastMod = formatDate(new Date().toLocaleDateString(dateLocalString, lastModDateOptions));
|
|
266
|
+
done();
|
|
267
|
+
log.success('\u{2705}', `Finished Building ${templatesCount} Article(s).`);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
resolve();
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// MARK: configureArticlesAndBuildTemplates
|
|
280
|
+
async function configureArticlesAndBuildTemplates(siteData, siteSettings, gulpPlugins) {
|
|
281
|
+
return await new Promise(function(done) {
|
|
282
|
+
if (!siteData.page) {
|
|
283
|
+
log.error('"page" is not defined in siteData!');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (articles.length === 0) {
|
|
287
|
+
log.error('Articles not found!');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const { page } = siteData;
|
|
291
|
+
const { articlesConfig } = page;
|
|
292
|
+
const { homePageArticlesList, articlesWithContractors, tradeHubPagesArticlesList, siteDetails } = articlesConfig;
|
|
293
|
+
|
|
294
|
+
articles.forEach(async (article) => {
|
|
295
|
+
const templateData = article;
|
|
296
|
+
const articlesWithContractorsKey = article.slug.replaceAll(/[-|\s]/ig, '_');
|
|
297
|
+
const trade = article.data.trade.slug.toLowerCase().replaceAll(/[-|\s]/ig, '_');
|
|
298
|
+
const contractors = await getContractors(article.data.trade.slug, siteSettings);
|
|
299
|
+
const tradeDisplayName = article?.data?.trade?.title?.toLowerCase();
|
|
300
|
+
// Append contractors
|
|
301
|
+
if (contractors && contractors.length) {
|
|
302
|
+
templateData.contractors = await processAndSortContractorList(contractors, 'reviewScore');
|
|
303
|
+
}
|
|
304
|
+
const articleLink = await `${siteDetails?.homepage}/${article.data.trade.slug}/${article.slug}.html`;
|
|
305
|
+
const tradeHubLink = await `${siteDetails?.homepage}/${article.data.trade.slug}/`;
|
|
306
|
+
const categoryPageLink = await `${siteDetails?.homepage}/`;
|
|
307
|
+
templateData.data.redirectLink = await `/${articleLink}`;
|
|
308
|
+
templateData.data.tradeHubPageLink = await `/${tradeHubLink}`;
|
|
309
|
+
templateData.data.categoryPageLink = await `/${categoryPageLink}`;
|
|
310
|
+
templateData.meta.canonicalURL = await `${siteDetails?.domain}/${articleLink}`;
|
|
311
|
+
templateData.data.loc = await `${siteDetails?.domain}/${articleLink}`;
|
|
312
|
+
templateData.data.lastMod = await formatDate(new Date(article.data.published).toLocaleDateString(dateLocalString, lastModDateOptions));
|
|
313
|
+
templateData.data.vertical = siteDetails.vertical;
|
|
314
|
+
templateData.data.trade.displayName = tradeDisplayName === 'hvac' ? 'heating and cooling' : tradeDisplayName;
|
|
315
|
+
|
|
316
|
+
const lastMod = formatDate(new Date(templateData.data.published).toLocaleDateString(dateLocalString, lastModDateOptions));
|
|
317
|
+
|
|
318
|
+
if (!tradeLookUp.includes(article.data.trade.slug)) {
|
|
319
|
+
tradeLookUp.push(article.data.trade.slug);
|
|
320
|
+
siteData.sitemap.push(
|
|
321
|
+
{
|
|
322
|
+
link: `${siteDetails.domain}/${tradeHubLink}`,
|
|
323
|
+
lastMod
|
|
324
|
+
}
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
siteData.sitemap.push(
|
|
329
|
+
{
|
|
330
|
+
link: `${siteDetails.domain}/${articleLink}`,
|
|
331
|
+
lastMod
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
templateData.data.sponsoredContent = siteDetails.data.sponsoredContent.article;
|
|
336
|
+
|
|
337
|
+
const zipCard = await getZipCardMarkup(templateData.data.trade, gulpPlugins);
|
|
338
|
+
const htmlContent = gulpPlugins.htmlParser.parse(templateData.data.content);
|
|
339
|
+
const contentHeadings = htmlContent.querySelectorAll('h2[id]');
|
|
340
|
+
if (zipCard) {
|
|
341
|
+
// find the middle section index and add flag isMiddleSection
|
|
342
|
+
const middleSectionIndex = Math.floor((contentHeadings.length) / 2);
|
|
343
|
+
htmlContent.querySelectorAll('h2[id]')[middleSectionIndex].insertAdjacentHTML('beforebegin', zipCard);
|
|
344
|
+
}
|
|
345
|
+
templateData.data.content = htmlContent;
|
|
346
|
+
|
|
347
|
+
await assign(articlesWithContractors, [trade, articlesWithContractorsKey], templateData);
|
|
348
|
+
|
|
349
|
+
await articleConfigsCount++;
|
|
350
|
+
|
|
351
|
+
if (articleConfigsCount === articles.length) {
|
|
352
|
+
if (Object.keys(articlesWithContractors).length) {
|
|
353
|
+
Object.entries(articlesWithContractors).forEach(async function([tradeName, values]) {
|
|
354
|
+
await sortArticlesByDate(Object.values(values));
|
|
355
|
+
if (!tradeHubPagesArticlesList[tradeName]) {
|
|
356
|
+
tradeHubPagesArticlesList[tradeName] = {};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (!tradeHubPagesArticlesList[tradeName].featured) {
|
|
360
|
+
tradeHubPagesArticlesList[tradeName].featured = [];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (!tradeHubPagesArticlesList[tradeName].top) {
|
|
364
|
+
tradeHubPagesArticlesList[tradeName].top = [];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (!tradeHubPagesArticlesList[tradeName].recent) {
|
|
368
|
+
tradeHubPagesArticlesList[tradeName].recent = [];
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (!tradeHubPagesArticlesList[tradeName].canonicalURL) {
|
|
372
|
+
tradeHubPagesArticlesList[tradeName].canonicalURL = `${siteDetails?.domain}/${tradeName}/`;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
tradeHubPagesArticlesList[tradeName].page = await siteDetails?.data?.trades?.filter((data) => data.slug === tradeName)[0];
|
|
376
|
+
|
|
377
|
+
Object.entries(values).forEach(function([, data], i) {
|
|
378
|
+
if (i === 0) {
|
|
379
|
+
tradeHubPagesArticlesList[tradeName].featured.push(data.data);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (showCostCalFor.includes(tradeName)) {
|
|
383
|
+
if (i >= 1) {
|
|
384
|
+
tradeHubPagesArticlesList[tradeName].recent.push(data.data);
|
|
385
|
+
tradeHubPagesArticlesList[tradeName].recentCount = tradeHubPagesArticlesList[tradeName].recent.length;
|
|
386
|
+
}
|
|
387
|
+
} else {
|
|
388
|
+
if (i > 0 && i < 3) {
|
|
389
|
+
tradeHubPagesArticlesList[tradeName].top.push(data.data);
|
|
390
|
+
tradeHubPagesArticlesList[tradeName].topCount = tradeHubPagesArticlesList[tradeName].top.length;
|
|
391
|
+
} else if (i >= 3) {
|
|
392
|
+
tradeHubPagesArticlesList[tradeName].recent.push(data.data);
|
|
393
|
+
tradeHubPagesArticlesList[tradeName].recentCount = tradeHubPagesArticlesList[tradeName].recent.length;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (homePageArticlesList.featured.length === 0 && data.data.isFeatured) {
|
|
398
|
+
homePageArticlesList.featured.push(data.data);
|
|
399
|
+
} else if (homePageArticlesList.top.length < 2 && !data.data.isFeatured && data.data.isTopArticle) {
|
|
400
|
+
homePageArticlesList.top.push(data.data);
|
|
401
|
+
} else if (!data.data.isTopArticle && !data.data.isFeatured) {
|
|
402
|
+
homePageArticlesList.recent.push(data.data);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
await buildTemplates(siteData, siteSettings, done);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
return async function() {
|
|
413
|
+
await configureGlobalVariables(siteData, siteSettings);
|
|
414
|
+
await getSiteDetails(siteData, siteSettings);
|
|
415
|
+
await getDetailedArticles(siteSettings);
|
|
416
|
+
return await configureArticlesAndBuildTemplates(siteData, siteSettings, gulpPlugins);
|
|
417
|
+
};
|
|
418
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* globals Promise */
|
|
2
|
+
var request = require('request');
|
|
3
|
+
var source = require('vinyl-source-stream');
|
|
4
|
+
|
|
5
|
+
function streamSharedCompsToDestination(gulp, siteSettings, folder, fileName) {
|
|
6
|
+
return new Promise(resolve => {
|
|
7
|
+
request(`https://${siteSettings.nodeEnv}/quote/resources/mod-site/shared-components/${folder}/${fileName}`)
|
|
8
|
+
.on('response', resp => {
|
|
9
|
+
if (resp.statusCode !== 200) {
|
|
10
|
+
throw new Error(`${resp.statusCode} Error while fetching ${fileName}`);
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
.pipe(source(fileName))
|
|
14
|
+
.pipe(gulp.dest(`${siteSettings.srcFolder}/shared-components/${folder}/`))
|
|
15
|
+
.on('finish', resolve);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getListOfSharedComponents(gulp, gulpPlugins, siteSettings, componentFolders) {
|
|
20
|
+
return componentFolders.map(folder => {
|
|
21
|
+
return new Promise(resolve => {
|
|
22
|
+
request(`https://${siteSettings.nodeEnv}/quote/resources/mod-site/shared-components/${folder}/all.json`, function(err, resp, body) {
|
|
23
|
+
if (resp.statusCode !== 200) {
|
|
24
|
+
throw new Error(`${resp.statusCode}: Error while fetching ${folder}/all.json`);
|
|
25
|
+
}
|
|
26
|
+
var listOfComponents = JSON.parse(body);
|
|
27
|
+
const componentPromises = listOfComponents.map(function(resource) {
|
|
28
|
+
return streamSharedCompsToDestination(gulp, siteSettings, folder, `${resource}`);
|
|
29
|
+
});
|
|
30
|
+
resolve(Promise.all(componentPromises));
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = function(gulp, gulpPlugins, siteSettings) {
|
|
37
|
+
return function() {
|
|
38
|
+
const { nodeEnv } = siteSettings;
|
|
39
|
+
if (!nodeEnv) {
|
|
40
|
+
throw new Error('Missing environment variables. Did you start with gulp instead of npm run...?');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const componentFolders = ['section-deals'];
|
|
44
|
+
|
|
45
|
+
return getListOfSharedComponents(gulp, gulpPlugins, siteSettings, componentFolders);
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -7,6 +7,7 @@ var path = require('path');
|
|
|
7
7
|
var buffer = require('gulp-buffer');
|
|
8
8
|
|
|
9
9
|
const fileNames = {
|
|
10
|
+
geolocationFileName: '',
|
|
10
11
|
modAlyticsFileName: '',
|
|
11
12
|
modUtilsFileName: '',
|
|
12
13
|
abandonmentJsFileName: '',
|
|
@@ -22,11 +23,16 @@ var resourceURL = '';
|
|
|
22
23
|
var pathSubdirectory = '';
|
|
23
24
|
var componentFolderPath = '';
|
|
24
25
|
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
const resourcePath = isQuotePageOrUseRelativePath ? `${doNotIncludeSrc ? '' : '{{#if this.src}}{{this.src}}{{/if}}'}resources/scripts/mod-alytics/` : '/resources/scripts/mod-alytics/';
|
|
26
|
+
function replaceHeadScripts(gulp, gulpPlugins, siteSettings, siteData) {
|
|
27
|
+
const resourcePath = isQuotePageOrUseRelativePath ? '{{#if this.src}}{{this.src}}{{/if}}resources/scripts' : '/resources/scripts';
|
|
28
28
|
return gulp.src(`${siteSettings.srcFolder}/${componentFolderPath}/head/head.html`)
|
|
29
|
-
|
|
29
|
+
.pipe(replace(/"(?:(?!"|")[\s\S])+(modalytics.*?)js"|"(?:(?!"|")[\s\S])+(geolocation.*?)js"/g, function(match) {
|
|
30
|
+
if (match.includes('modalytics')) {
|
|
31
|
+
return `"${resourcePath}/mod-alytics/${fileNames.modAlyticsFileName}"`;
|
|
32
|
+
} else if (match.includes('geolocation')) {
|
|
33
|
+
return `"${resourcePath}/geolocation/${fileNames.geolocationFileName}"`;
|
|
34
|
+
}
|
|
35
|
+
}))
|
|
30
36
|
.pipe(gulp.dest(`${siteSettings.srcFolder}/${componentFolderPath}/head`));
|
|
31
37
|
}
|
|
32
38
|
function replaceFootAssetScripts(gulp, gulpPlugins, siteSettings, siteData) {
|
|
@@ -187,6 +193,16 @@ const TASKS = {
|
|
|
187
193
|
srcReplaceFn: replaceFootAssetScripts,
|
|
188
194
|
additionalSrcReplaceFns: []
|
|
189
195
|
},
|
|
196
|
+
copyGeolocation: {
|
|
197
|
+
url: 'shared-resources/scripts/geolocation/geolocation.min.js',
|
|
198
|
+
config: {
|
|
199
|
+
fileName: 'geolocationFileName',
|
|
200
|
+
dest: 'scripts/geolocation',
|
|
201
|
+
mapUrl: 'shared-resources/scripts/geolocation/geolocation.min.js.map',
|
|
202
|
+
},
|
|
203
|
+
srcReplaceFn: null,
|
|
204
|
+
additionalSrcReplaceFns: []
|
|
205
|
+
},
|
|
190
206
|
copyModalytics: {
|
|
191
207
|
url: 'mod-alytics/modalytics.min.js',
|
|
192
208
|
config: {
|
|
@@ -194,7 +210,7 @@ const TASKS = {
|
|
|
194
210
|
dest: 'scripts/mod-alytics',
|
|
195
211
|
mapUrl: 'mod-alytics/modalytics.min.js.map',
|
|
196
212
|
},
|
|
197
|
-
srcReplaceFn:
|
|
213
|
+
srcReplaceFn: replaceHeadScripts,
|
|
198
214
|
additionalSrcReplaceFns: []
|
|
199
215
|
},
|
|
200
216
|
copyAbandonmentComponentStyles: {
|
package/gulp-tasks/serve.js
CHANGED
|
@@ -4,11 +4,11 @@ module.exports.src = function(gulp, gulpPlugins, siteSettings, siteData) {
|
|
|
4
4
|
var runSequence = require('run-sequence');
|
|
5
5
|
var sequenceOpts;
|
|
6
6
|
if (siteData.useTypescript) {
|
|
7
|
-
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'grab-form-helpers', 'templates', 'styles', 'compile', 'grab-tooltips-json', 'combine-files', 'grab-images', 'js-lint'];
|
|
7
|
+
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'get-default-trade-questions', 'grab-form-helpers', 'templates', 'styles', 'compile', 'grab-tooltips-json', 'combine-files', 'grab-images', 'js-lint'];
|
|
8
8
|
} else if (siteData.isQSPage) {
|
|
9
|
-
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'grab-form-helpers', 'templates', 'styles', 'grab-theme-json', 'grab-tooltips-json', 'combine-files', 'grab-images', 'js-lint'];
|
|
9
|
+
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'get-default-trade-questions', 'grab-form-helpers', 'templates', 'styles', 'grab-theme-json', 'grab-tooltips-json', 'combine-files', 'grab-images', 'js-lint'];
|
|
10
10
|
} else {
|
|
11
|
-
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'grab-form-helpers', 'templates', 'styles', 'grab-tooltips-json', 'combine-files', 'grab-images','grab-global-images', 'js-lint'];
|
|
11
|
+
sequenceOpts = ['clean', 'add-editorconfig', 'grab-cdn', 'grab-shared-components', 'grab-shared-scripts', 'get-default-trade-questions', 'grab-form-helpers', 'templates', 'styles', 'grab-tooltips-json', 'combine-files', 'grab-images', 'grab-global-images', 'js-lint'];
|
|
12
12
|
}
|
|
13
13
|
runSequence(...sequenceOpts, () => {
|
|
14
14
|
// Run a BrowserSync server
|
|
@@ -38,10 +38,10 @@ module.exports.src = function(gulp, gulpPlugins, siteSettings, siteData) {
|
|
|
38
38
|
// If templates changed, rerun templates task
|
|
39
39
|
if (!siteData.useTypescript && !siteData.isQSPage) {
|
|
40
40
|
gulp.watch(siteSettings.srcFolder + '/' + siteSettings.templatesSubfolder + '/**/*.html', function() {
|
|
41
|
-
runSequence('templates','grab-global-images')
|
|
41
|
+
runSequence('templates', 'grab-global-images');
|
|
42
42
|
});
|
|
43
43
|
} else {
|
|
44
|
-
gulp.watch(siteSettings.srcFolder + '/' + siteSettings.templatesSubfolder + '/**/*.html', ['templates'])
|
|
44
|
+
gulp.watch(siteSettings.srcFolder + '/' + siteSettings.templatesSubfolder + '/**/*.html', ['templates']);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// If styles changed, rerun styles task
|
package/gulp-tasks/tasks.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = function() {
|
|
|
40
40
|
return require(opts.gulpTasksFolderPath + '/grab-cdn')(opts.gulp, opts.gulpPlugins, opts.gulpSettings, opts.siteData);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
},
|
|
44
44
|
|
|
45
45
|
// Grab form helpers files from CDN
|
|
46
46
|
'grab-form-helpers': {
|
|
@@ -356,7 +356,7 @@ module.exports = function() {
|
|
|
356
356
|
|
|
357
357
|
return require(opts.gulpTasksFolderPath + '/grab-images')(opts.gulp, opts.gulpSettings, opts.siteData);
|
|
358
358
|
}
|
|
359
|
-
|
|
359
|
+
},
|
|
360
360
|
|
|
361
361
|
// Get global images
|
|
362
362
|
'grab-global-images': {
|
|
@@ -430,7 +430,7 @@ module.exports = function() {
|
|
|
430
430
|
|
|
431
431
|
return require(opts.gulpTasksFolderPath + '/grab-tooltips-json')(opts.gulp, opts.gulpPlugins, opts.gulpSettings, opts.siteData);
|
|
432
432
|
}
|
|
433
|
-
|
|
433
|
+
},
|
|
434
434
|
|
|
435
435
|
// copy resources directory into dist
|
|
436
436
|
'copy-resources-to-dist': {
|
|
@@ -488,6 +488,39 @@ module.exports = function() {
|
|
|
488
488
|
|
|
489
489
|
return require('./copy-xml-files-to-dist')(opts.gulp, opts.gulpSettings);
|
|
490
490
|
}
|
|
491
|
+
},
|
|
492
|
+
|
|
493
|
+
'grab-section-deals-components': {
|
|
494
|
+
subtasks: [],
|
|
495
|
+
func: function(opts) {
|
|
496
|
+
if ('undefined' === typeof opts.gulpTasksFolderPath) {
|
|
497
|
+
opts.gulpTasksFolderPath = '.';
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return require('./grab-section-deals-components')(opts.gulp, opts.gulpPlugins, opts.gulpSettings, opts.siteData);
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
'grab-mhsadmin-data': {
|
|
505
|
+
subtasks: [],
|
|
506
|
+
func: function(opts) {
|
|
507
|
+
if ('undefined' === typeof opts.gulpTasksFolderPath) {
|
|
508
|
+
opts.gulpTasksFolderPath = '.';
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return require('./grab-mhsadmin-data')(opts.gulp, opts.gulpPlugins, opts.gulpSettings, opts.siteData);
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
|
|
515
|
+
'get-default-trade-questions': {
|
|
516
|
+
subtasks: [],
|
|
517
|
+
func: function(opts) {
|
|
518
|
+
if ('undefined' === typeof opts.gulpTasksFolderPath) {
|
|
519
|
+
opts.gulpTasksFolderPath = '.';
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return require('./get-default-trade-questions')(opts.gulp, opts.gulpPlugins, opts.gulpSettings, opts.siteData);
|
|
523
|
+
}
|
|
491
524
|
}
|
|
492
525
|
};
|
|
493
526
|
|