mod-build 3.6.75-beta.2 → 4.0.0-alpha.2

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 (62) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +18 -0
  3. package/CHANGELOG.md +2 -252
  4. package/README.md +16 -263
  5. package/gulp-tasks/grab-cdn.js +0 -10
  6. package/package.json +18 -68
  7. package/siteconfig.js +38 -0
  8. package/src/data/footer.js +117 -0
  9. package/src/data/seasons.js +5 -7
  10. package/src/index.html +18 -0
  11. package/src/main.js +45 -0
  12. package/src/scripts/has-qs-params.js +6 -5
  13. package/src/scripts/url-cleaner.js +3 -3
  14. package/src/scripts/utils.js +178 -0
  15. package/src/styles/home.scss +1 -0
  16. package/src/templates/_partials/scripts/deferred-styles.html +16 -16
  17. package/src/templates/_partials/scripts/vwo-redirect-callback.html +43 -45
  18. package/src/templates/components/head.html +70 -0
  19. package/tasks/clean.js +13 -0
  20. package/tasks/grab-cdn.js +107 -0
  21. package/tasks/grab-form-helpers.js +94 -0
  22. package/tasks/grab-shared-components.js +81 -0
  23. package/tasks/grab-shared-scripts.js +267 -0
  24. package/tasks/serve.js +15 -0
  25. package/tasks/templates.js +168 -0
  26. package/template.js +801 -0
  27. package/vite.config.js +56 -0
  28. package/.eslintrc.yml +0 -59
  29. package/src/data/common.js +0 -704
  30. package/src/data/components/qs-footer.js +0 -55
  31. package/src/data/components/quote-footer.js +0 -73
  32. package/src/scripts/apt-block.js +0 -919
  33. package/src/scripts/components/custom-selects.js +0 -48
  34. package/src/scripts/components/radio-panels.js +0 -45
  35. package/src/scripts/es6-1.js +0 -6
  36. package/src/scripts/es6-2.js +0 -2
  37. package/src/scripts/qs-form.js +0 -839
  38. package/src/scripts/vendor/maxmind-geoip2.js +0 -2
  39. package/src/scripts/vendor/swiper.min.js +0 -13
  40. package/src/styles/apt-block.scss +0 -888
  41. package/src/templates/_partials/apt-block.html +0 -30
  42. package/src/templates/_partials/scripts/analytics.html +0 -4
  43. package/src/templates/_partials/scripts/go-page-hiding-snippet.html +0 -8
  44. package/src/templates/_partials/scripts/google-maps.html +0 -1
  45. package/src/templates/_partials/scripts/google-optimize.html +0 -12
  46. package/src/templates/_partials/scripts/gtm-editorials/body/google-tag-manager-body.html +0 -5
  47. package/src/templates/_partials/scripts/gtm-editorials/head/google-tag-manager-head.html +0 -10
  48. package/src/templates/_partials/scripts/gtm-hil/body/google-tag-manager-body.html +0 -5
  49. package/src/templates/_partials/scripts/gtm-hil/head/google-tag-manager-head.html +0 -10
  50. package/src/templates/_partials/scripts/gtm-pro/body/google-tag-manager-body.html +0 -5
  51. package/src/templates/_partials/scripts/gtm-pro/head/google-tag-manager-head.html +0 -10
  52. package/src/templates/_partials/scripts/gtm-quote/body/google-tag-manager-body.html +0 -5
  53. package/src/templates/_partials/scripts/gtm-quote/head/google-tag-manager-head.html +0 -9
  54. package/src/templates/_partials/scripts/gtm-whitelabel/body/mod-google-tag-manager-body.html +0 -5
  55. package/src/templates/_partials/scripts/gtm-whitelabel/body/non-mod-google-tag-manager-body.html +0 -5
  56. package/src/templates/_partials/scripts/gtm-whitelabel/head/mod-google-tag-manager-head.html +0 -10
  57. package/src/templates/_partials/scripts/gtm-whitelabel/head/non-mod-google-tag-manager-head.html +0 -9
  58. package/src/templates/_partials/scripts/gtm-wordpress/body/google-tag-manager-body.html +0 -5
  59. package/src/templates/_partials/scripts/gtm-wordpress/head/google-tag-manager-head.html +0 -9
  60. package/src/templates/_partials/scripts/visual-website-optimizer.html +0 -5
  61. package/src/templates/index.html +0 -46
  62. /package/{src → public}/favicon.ico +0 -0
@@ -0,0 +1,70 @@
1
+ <!-- an example of the head component for v4.0.0 -->
2
+ <meta charset="UTF-8" />
3
+ <link rel="icon" type="image/svg+xml" href="/{{#if page.headConfig.faviconPath}}{{page.headConfig.faviconPath}}{{else}}favicon.svg"{{/if}} />
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
5
+
6
+ <!-- assets links afterBegin -->
7
+ {{#if page.headConfig.useModAnalytics}}
8
+ <script src="https://{{this.resourceDomain}}/quote/resources/mod-alytics/modalytics.min.js" {{#if page.headConfig.deferModAnalytics}}defer{{/if}} {{#if page.headConfig.asyncModAnalytics}}async{{/if}}></script>
9
+ {{/if}}
10
+
11
+ <!-- Include vwo setup -->
12
+ {{#xif "this.page.headConfig.vwoSetup.vwoPathArray.indexOf(this.path) > -1" }}
13
+ <link rel="preconnect" href="https://dev.visualwebsiteoptimizer.com">
14
+ <!-- Do not double hit our analytical resources (Heap/Google Analytics) if the page is going to be redirected by a VWO a/b test-->
15
+ <script src="{{ resolveAlias '@/scripts/vendor/visual-website-optimizer.js'}}"></script>
16
+ {{else}}
17
+ <script src="{{ resolveAlias '@/scripts/url-cleaner.js'}}"></script>
18
+ {{/xif}}
19
+
20
+ {{#unless page.headConfig.disableRobots}}
21
+ <meta name="robots" content="{{#if page.headConfig.robotsCsv}}{{page.headConfig.robotsCsv}}{{else}}noindex,nofollow{{/if}}"/>
22
+ {{/unless}}
23
+
24
+ {{#unless page.headConfig.disableOgTags}}
25
+ <meta property="og:title" content="{{page.headConfig.title}}" />
26
+ <meta property="og:description" content="{{page.headConfig.description}}" />
27
+ {{/unless}}
28
+
29
+ <meta name="description" property="description" content="{{page.headConfig.description}}" />
30
+ <meta name="keywords" property="keywords" content="{{page.headConfig.keywords}}" />
31
+
32
+ <!-- preconnect google fonts -->
33
+ <link rel="preconnect" href="https://fonts.googleapis.com">
34
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
35
+ {{#if page.headConfig.preConnect}}
36
+ {{#each page.headConfig.preConnect}}
37
+ <link
38
+ {{#if this.rel}}rel="{{this.rel}}"{{/if}}
39
+ {{#if this.href}}href="{{this.href}}"{{/if}}
40
+ {{#if this.as}}as="{{this.as}}"{{/if}}
41
+ {{#if this.crossorigin}}crossorigin="{{this.crossorigin}}"{{/if}}
42
+ {{#if this.media}}media="{{this.media}}"{{/if}}
43
+ {{#if this.type}}type="{{this.type}}"{{/if}}
44
+ {{#if this.fetchpriority}}fetchpriority="{{this.fetchpriority}}"{{/if}}
45
+ >
46
+ {{/each}}
47
+ {{/if}}
48
+
49
+ <!-- site title -->
50
+ <title>
51
+ {{#if page.headConfig.inverseTitle}}
52
+ {{#unless page.headConfig.hideTitleCompanyName}}{{company_name}} | {{/unless}}
53
+ {{#if this.pageTitle}}
54
+ {{this.pageTitle}}
55
+ {{else}}
56
+ {{#if page.headConfig.title}}
57
+ {{page.headConfig.title}}
58
+ {{/if}}
59
+ {{/if}}
60
+ {{else}}
61
+ {{#if this.pageTitle}}
62
+ {{this.pageTitle}}
63
+ {{else}}
64
+ {{#if page.headConfig.title}}
65
+ {{page.headConfig.title}}
66
+ {{/if}}
67
+ {{/if}}
68
+ {{#unless page.headConfig.hideTitleCompanyName}} | {{company_name}}{{/unless}}
69
+ {{/if}}
70
+ </title>
package/tasks/clean.js ADDED
@@ -0,0 +1,13 @@
1
+ import { deleteSync } from 'del';
2
+ import { defaultSettings } from '../siteconfig';
3
+
4
+ const clean = (done) => {
5
+ deleteSync([
6
+ `src/${defaultSettings.tmpFolder}/`,
7
+ `${defaultSettings.distFolder}/`
8
+ ]);
9
+ console.log('clean finished');
10
+ done();
11
+ };
12
+
13
+ export default clean;
@@ -0,0 +1,107 @@
1
+ import { defaultSettings, siteData } from '../siteconfig.js'
2
+ import { templateData } from '../template.js';
3
+ import axios from 'axios';
4
+ import { createWriteStream } from 'node:fs';
5
+ import * as stream from 'node:stream';
6
+ import { promisify } from 'node:util';
7
+ import fs from 'node:fs';
8
+
9
+ function streamToDestination(inputPath, destPath, fileName) {
10
+ const finished = promisify(stream.finished);
11
+ const url = `https://${defaultSettings.resourceDomain}${inputPath}`;
12
+
13
+ return new Promise(resolve => {
14
+ if (!fs.existsSync(`src/${destPath}`)) {
15
+ fs.mkdirSync(`src/${destPath}`, { recursive: true });
16
+ }
17
+
18
+ // if file exists, do not create it again
19
+ if (fs.existsSync(`src/${destPath}${fileName}`)) {
20
+ resolve();
21
+ } else {
22
+ const writer = createWriteStream(`src/${destPath}${fileName}`);
23
+ const options = {
24
+ url,
25
+ method: 'get',
26
+ responseType: 'stream',
27
+ };
28
+
29
+ axios(options).then(resp => {
30
+ if (resp.status !== 200) {
31
+ throw new Error(`${resp.status}: Error while fetching ${url}`);
32
+ }
33
+ console.log('axios grab-cdn running');
34
+ resp.data.pipe(writer);
35
+ console.log(`src/${destPath}${fileName} created...`);
36
+ return finished(writer);
37
+ }).then(() => {
38
+ resolve();
39
+ }).catch(error => {
40
+ console.error(error);
41
+ resolve();
42
+ });
43
+ }
44
+ });
45
+ }
46
+
47
+ export default async function(done) {
48
+ const { nodeEnv, isLocal } = defaultSettings;
49
+ const { isQSPage, isWhiteLabel, domain } = siteData;
50
+ const { page } = templateData();
51
+ const { themeFile } = page;
52
+ const isModWhiteLabel = isWhiteLabel && !isQSPage
53
+ const domainHasModernize = domain.indexOf('modernize') > -1;
54
+
55
+ let externalResources;
56
+ // listing of Static Resources sub-path and site destination paths
57
+ // key: inputPath, value: destPath
58
+
59
+ externalResources = {
60
+ '/quote/resources/mod-site/templates/scripts/trusted-form.html': ['/templates/scripts/', 'trusted-form.html']
61
+ };
62
+
63
+ // grab footer modals and place under the resources
64
+ Object.assign(externalResources, {
65
+ '/quote/resources/shared-resources/templates/modals/about/': ['/resources/templates/modals/about/', 'index.html'],
66
+ '/quote/resources/shared-resources/templates/modals/privacy/': ['/resources/templates/modals/privacy/', 'index.html'],
67
+ '/quote/resources/shared-resources/templates/modals/terms/': ['/resources/templates/modals/terms/', 'index.html'],
68
+ '/quote/resources/shared-resources/templates/modals/contact-us/': ['/resources/templates/modals/contact-us/', 'index.html'],
69
+ '/quote/resources/shared-resources/templates/modals/faq/': ['/resources/templates/modals/faq/', 'index.html']
70
+ })
71
+
72
+ Object.assign(externalResources, {'/quote/resources/mod-site/templates/scripts/jornaya.html': ['/templates/scripts/', 'jornaya.html']});
73
+
74
+ if (isModWhiteLabel || domainHasModernize) {
75
+ Object.assign(externalResources, {'/quote/resources/mod-site/templates/scripts/recaptcha.html': ['/templates/scripts/', 'recaptcha.html']});
76
+ }
77
+
78
+ // local dev files
79
+ const remoteFilesForLocalDev = {
80
+ '/quote/resources/mod-site/scripts/vendor/maxmind-geoip2.js': ['/temp/scripts/', 'maxmind-geoip2.js']
81
+ };
82
+
83
+ // theme JSON
84
+ if (isQSPage) {
85
+ Object.assign(externalResources, {
86
+ [`/quote/resources/data/themes/${themeFile}.json`]: ['/data/', 'theme.json']
87
+ });
88
+ }
89
+
90
+ if (!nodeEnv) {
91
+ throw new Error('Missing environment variables. Did you start with gulp instead of npm run...?');
92
+ }
93
+
94
+ // only save modform/utils if its local development
95
+ if (isLocal) {
96
+ externalResources = { ...externalResources, ...remoteFilesForLocalDev };
97
+ }
98
+
99
+ const filesPromiseMap = Object.keys(externalResources).map(async key => {
100
+ const destinationPath = externalResources[key][0];
101
+ const fileName = externalResources[key][1];
102
+ await streamToDestination(key, destinationPath, fileName);
103
+ });
104
+
105
+ await Promise.all(filesPromiseMap);
106
+ done();
107
+ };
@@ -0,0 +1,94 @@
1
+ import { defaultSettings } from '../siteconfig.js'
2
+ import axios from 'axios';
3
+ import { createWriteStream } from 'node:fs';
4
+ import * as stream from 'node:stream';
5
+ import { promisify } from 'node:util';
6
+ import fs from 'node:fs';
7
+
8
+ const resourcePath = 'quote/resources/mod-form/form';
9
+
10
+ // helper to allow us to define an "end" event to multiple streams
11
+ const streamToDestination = (destPath, fileName) => {
12
+ if (!fileName) {
13
+ return false;
14
+ }
15
+
16
+ const finished = promisify(stream.finished);
17
+ const url = `https://${defaultSettings.resourceDomain}/${resourcePath}/${fileName}`;
18
+
19
+ return new Promise(resolve => {
20
+ const folderPath = `${defaultSettings.srcFolder}/${destPath}`;
21
+
22
+ if (!fs.existsSync(folderPath)) {
23
+ fs.mkdirSync(folderPath, { recursive: true });
24
+ }
25
+
26
+ // if file exists, do not create it again
27
+ if (fs.existsSync(`${folderPath}/${fileName}`)) {
28
+ resolve();
29
+ } else {
30
+ const writer = createWriteStream(`${folderPath}/${fileName}`)
31
+ const options = {
32
+ url,
33
+ method: 'get',
34
+ responseType: 'stream'
35
+ };
36
+
37
+ axios(options).then(resp => {
38
+ if (resp.status !== 200) {
39
+ throw new Error(`${resp.status}: Error while fetching ${url}`);
40
+ }
41
+ resp.data.pipe(writer);
42
+ console.log(`${destPath}/${fileName} created...`);
43
+ return finished(writer);
44
+ }).then(() => {
45
+ resolve();
46
+ }).catch(error => {
47
+ console.error(error);
48
+ resolve();
49
+ });
50
+ }
51
+ });
52
+ }
53
+
54
+ async function getHelpers() {
55
+ let helpers = [];
56
+ await new Promise(resolve => {
57
+ const options = {
58
+ url: `https://${defaultSettings.resourceDomain}/${resourcePath}/chunks.txt`,
59
+ method: 'get'
60
+ }
61
+
62
+ axios(options).then(resp => {
63
+ if (resp.status !== 200) {
64
+ throw new Error(`${resp.status}: Error while fetching ${url}`);
65
+ }
66
+ helpers = resp.data.split('\n');
67
+ resolve();
68
+ }).then(() => {
69
+ resolve();
70
+ }).catch(error => {
71
+ console.error(error);
72
+ resolve();
73
+ });
74
+ });
75
+
76
+ return helpers;
77
+ }
78
+
79
+ export default async function(done) {
80
+ const { nodeEnv } = defaultSettings;
81
+ const helpers = await getHelpers(defaultSettings);
82
+
83
+ if (!nodeEnv) {
84
+ throw new Error('Missing environment variables. Did you start with gulp instead of npm run...?');
85
+ }
86
+ const destinationPath = '/resources/scripts/helpers/';
87
+ const filesPromiseMap = helpers.map(async helper => {
88
+ const fileName = helper;
89
+ await streamToDestination(destinationPath, fileName);
90
+ });
91
+
92
+ await Promise.all(filesPromiseMap);
93
+ done();
94
+ }
@@ -0,0 +1,81 @@
1
+ import { defaultSettings, siteData } from '../siteconfig.js'
2
+ import axios from 'axios';
3
+ import { createWriteStream } from 'node:fs';
4
+ import * as stream from 'node:stream';
5
+ import { promisify } from 'node:util';
6
+ import fs from 'node:fs';
7
+
8
+ const resourcePath = 'quote/resources/mod-site';
9
+ const componentFolders = ['accessible-components'];
10
+
11
+ const streamSharedCompsToDestination = (defaultSettings, folder, fileName) => {
12
+ const finished = promisify(stream.finished);
13
+
14
+ return new Promise(resolve => {
15
+ const folderPath = `${defaultSettings.srcFolder}/${folder}`;
16
+ const componentFolderPath = fileName.split('/')[0];
17
+
18
+ if (!fs.existsSync(folderPath)) {
19
+ fs.mkdirSync(folderPath, { recursive: true });
20
+ }
21
+
22
+ if (!fs.existsSync(`${folderPath}/${componentFolderPath}`)) {
23
+ fs.mkdirSync(`${folderPath}/${componentFolderPath}`, { recursive: true });
24
+ }
25
+
26
+ // if file exists, do not create it again
27
+ if (fs.existsSync(`${folderPath}/${fileName}`)) {
28
+ resolve();
29
+ } else {
30
+ const writer = createWriteStream(`${folderPath}/${fileName}`)
31
+ const options = {
32
+ url: `https://${defaultSettings.resourceDomain}/${resourcePath}/${folder}/${fileName}`,
33
+ method: 'get',
34
+ responseType: 'stream'
35
+ };
36
+
37
+ axios(options).then(resp => {
38
+ if (resp.status !== 200) {
39
+ throw new Error(`${resp.status}: Error while fetching ${url}`);
40
+ }
41
+ console.log(`${folderPath}/${fileName} created...`);
42
+ resp.data.pipe(writer);
43
+ return finished(writer);
44
+ }).then(() => {
45
+ resolve();
46
+ }).catch(error => {
47
+ console.error(error);
48
+ resolve();
49
+ });
50
+ }
51
+ });
52
+ }
53
+
54
+ const getListOfSharedComponents = (defaultSettings, componentFolders) => {
55
+ return componentFolders.map(folder => {
56
+ return new Promise(resolve => {
57
+ axios.get(`https://${defaultSettings.resourceDomain}/${resourcePath}/${folder}/all.json`)
58
+ .then(resp => {
59
+ if (resp.status !== 200) {
60
+ throw new Error(`${resp.status}: Error while fetching ${folder}/all.json`);
61
+ }
62
+ const listOfComponents = resp.data;
63
+ const componentPromises = listOfComponents.map(resource => {
64
+ return streamSharedCompsToDestination(defaultSettings, folder, `${resource}`);
65
+ });
66
+
67
+ resolve(Promise.all(componentPromises));
68
+ })
69
+ .catch(err => {
70
+ console.log(defaultSettings.nodeEnv);
71
+ throw new Error(`Error while fetching ${folder}/all.json: ${err.message}`);
72
+ });
73
+ });
74
+ });
75
+ }
76
+
77
+ export default function(done) {
78
+ console.log('running grab-shared-components');
79
+ getListOfSharedComponents(defaultSettings, componentFolders);
80
+ done();
81
+ }
@@ -0,0 +1,267 @@
1
+ import { defaultSettings, siteData } from '../siteconfig.js'
2
+ import axios from 'axios';
3
+ import { createWriteStream } from 'node:fs';
4
+ import * as stream from 'node:stream';
5
+ import { promisify } from 'node:util';
6
+ import fs from 'node:fs';
7
+ import gulp from 'gulp';
8
+ import tap from 'gulp-tap';
9
+ import hash from 'gulp-hash';
10
+ import replace from 'gulp-replace';
11
+ import { getFileFromURL } from '../src/scripts/utils.js';
12
+
13
+ let fileNames = {
14
+ modAlyticsFileName: '',
15
+ modUtilsFileName: '',
16
+ abandonmentJsFileName: '',
17
+ footerComponentJsFileName: '',
18
+ modFooterStylesFileName: '',
19
+ qsFooterStylesFileName: '',
20
+ homeownerFormFileName: ''
21
+ };
22
+
23
+ let isQuotePageOrUseRelativePath = false;
24
+ let resourceURL = '';
25
+ let pathSubdirectory = '';
26
+ let componentFolderPath = '';
27
+
28
+ function replaceModalyticsSrc(gulp, defaultSettings) {
29
+ const resourcePath = isQuotePageOrUseRelativePath ? `${pathSubdirectory}{{#if this.src}}{{this.src}}{{/if}}resources/scripts/mod-alytics/` : '/resources/scripts/mod-alytics/';
30
+ return gulp.src(`${defaultSettings.srcFolder}/${componentFolderPath}/head/head.html`)
31
+ .pipe(replace(/".*(modalytics).*"/, `"${resourcePath}${fileNames.modAlyticsFileName}"`))
32
+ .pipe(gulp.dest(`${defaultSettings.srcFolder}/${componentFolderPath}/head`));
33
+ }
34
+
35
+ function replaceFootAssetScripts(gulp, defaultSettings) {
36
+ const resourcePath = isQuotePageOrUseRelativePath ? `${pathSubdirectory}{{#if this.nodeModulesPath}}{{this.nodeModulesPath}}{{/if}}resources/scripts` : '/resources/scripts';
37
+ return gulp.src(`${defaultSettings.srcFolder}/${componentFolderPath}/foot-assets/foot-assets.html`)
38
+ .pipe(replace(/"(?:(?!"|js")[\s\S])+(modutils|mod-utils.*?)js"|"(?:(?!"|")[\s\S])+(footer\/footer-component.*?)js"|"(?:(?!"|")[\s\S])+(mod-form\/form.*?)js"/g, function(match) {
39
+ if (match.includes('mod-form/form')) {
40
+ return `"${resourcePath}/mod-form/form/${fileNames.homeownerFormFileName}"`;
41
+ } else if (match.includes('modutils') || match.includes('mod-utils')) {
42
+ return `"${resourcePath}/mod-utils/${fileNames.modUtilsFileName}"`;
43
+ } else if (match.includes('footer-component')) {
44
+ return `"${resourcePath}/footer/${fileNames.footerComponentJsFileName}"`;
45
+ }
46
+ }))
47
+ .pipe(gulp.dest(`${defaultSettings.srcFolder}/${componentFolderPath}/foot-assets`))
48
+ .on('end', function() {
49
+ console.log('>> FINISHED replacing foot asset scripts');
50
+ });
51
+ }
52
+
53
+ function replaceAbandonmentJsCssSrc(gulp, defaultSettings) {
54
+ const jsResourcePath = isQuotePageOrUseRelativePath ? `${pathSubdirectory}resources/scripts/abandonment/` : '/resources/scripts/abandonment/';
55
+ const cssResourcePath = isQuotePageOrUseRelativePath ? `${pathSubdirectory}resources/styles/components/abandonment/` : '/resources/styles/components/abandonment/';
56
+ return gulp.src(defaultSettings.srcFolder + '/templates/abandonment/*.html')
57
+ .pipe(replace(/"(?:(?!"|")[\s\S])+(abandonment\/abandonment.*?)js"/, `"${jsResourcePath}${fileNames.abandonmentJsFileName}"`))
58
+ .pipe(replace(/"(?:(?!"|")[\s\S])+(components\/abandonment\/abandonment.*?)css"/, `"${cssResourcePath}${fileNames.abandonmentStylesFileName}"`))
59
+ .pipe(gulp.dest(defaultSettings.srcFolder + '/templates/abandonment'));
60
+ }
61
+
62
+ function replaceFooterStylesReference(gulp, defaultSettings, siteData) {
63
+ if (siteData.siteData && siteData.siteData.useRelativePathForResources === true) {
64
+ return gulp.src(defaultSettings.srcFolder + '/resources/scripts/footer/' + fileNames.footerComponentJsFileName)
65
+ .pipe(replace(/concat\((?:(?!concat\(|\))[\s\S])+(components\/footer\/mod.*?)\)/, `concat("${pathSubdirectory}resources/styles/components/footer/` + fileNames.modFooterStylesFileName + '")'))
66
+ .pipe(replace(/concat\((?:(?!concat\(|\))[\s\S])+(components\/footer\/qs.*?)\)/, `concat("${pathSubdirectory}resources/styles/components/footer/` + fileNames.qsFooterStylesFileName + '")'))
67
+ .pipe(gulp.dest(defaultSettings.srcFolder + '/resources/scripts/footer'))
68
+ } else if (!siteData.siteData || siteData.siteData && !siteData.siteData.isQuotePage) {
69
+ return gulp.src(defaultSettings.srcFolder + '/resources/scripts/footer/' + fileNames.footerComponentJsFileName)
70
+ .pipe(replace(/concat\((?:(?!concat\(|\))[\s\S])+(components\/footer\/mod.*?)\)/, 'concat("/resources/styles/components/footer/' + fileNames.modFooterStylesFileName + '")'))
71
+ .pipe(replace(/concat\((?:(?!concat\(|\))[\s\S])+(components\/footer\/qs.*?)\)/, 'concat("/resources/styles/components/footer/' + fileNames.qsFooterStylesFileName + '")'))
72
+ .pipe(gulp.dest(defaultSettings.srcFolder + '/resources/scripts/footer'))
73
+ }
74
+ }
75
+
76
+ function replaceFooterStylesReferenceInMap(gulp, defaultSettings, siteData) {
77
+ if (siteData.siteData && siteData.siteData.useRelativePathForResources === true) {
78
+ return gulp.src(defaultSettings.srcFolder + '/resources/scripts/footer/footer-component.min.js.map')
79
+ .pipe(replace(/\`(?:(?!\`|\`)[\s\S])+(components\/footer\/mod.*?)\`/, '`' + pathSubdirectory + 'resources/styles/components/footer/' + fileNames.modFooterStylesFileName + '`'))
80
+ .pipe(replace(/\`(?:(?!\`|\`)[\s\S])+(components\/footer\/mod.*?)\`/, '`' + pathSubdirectory + 'resources/styles/components/footer/' + fileNames.qsFooterStylesFileName + '`'))
81
+ .pipe(gulp.dest(defaultSettings.srcFolder + '/resources/scripts/footer'));
82
+ } else if (!siteData.siteData || siteData.siteData && !siteData.siteData.isQuotePage) {
83
+ return gulp.src(defaultSettings.srcFolder + '/resources/scripts/footer/footer-component.min.js.map')
84
+ .pipe(replace(/\`(?:(?!\`|\`)[\s\S])+(components\/footer\/mod.*?)\`/, '`/resources/styles/components/footer/' + fileNames.modFooterStylesFileName + '`'))
85
+ .pipe(replace(/\`(?:(?!\`|\`)[\s\S])+(components\/footer\/mod.*?)\`/, '`/resources/styles/components/footer/' + fileNames.qsFooterStylesFileName + '`'))
86
+ .pipe(gulp.dest(defaultSettings.srcFolder + '/resources/scripts/footer'));
87
+ }
88
+ }
89
+
90
+ const TASKS = {
91
+ copyModutils: {
92
+ url: 'mod-utils/modutils.min.js',
93
+ config: {
94
+ fileName: 'modUtilsFileName',
95
+ dest: 'scripts/mod-utils',
96
+ mapUrl: 'mod-utils/modutils.min.js.map'
97
+ },
98
+ srcReplaceFn: null,
99
+ additionalSrcReplaceFns: []
100
+ },
101
+ copyFooterComponentJs: {
102
+ url: 'shared-resources/scripts/footer/footer-component.min.js',
103
+ config: {
104
+ fileName: 'footerComponentJsFileName',
105
+ dest: 'scripts/footer',
106
+ mapUrl: 'shared-resources/scripts/footer/footer-component.min.js.map'
107
+ },
108
+ srcReplaceFn: null,
109
+ additionalSrcReplaceFns: []
110
+ },
111
+ copyHomeownerForm: {
112
+ url: 'mod-form/form/homeowner.min.js',
113
+ config: {
114
+ fileName: 'homeownerFormFileName',
115
+ dest: 'scripts/mod-form/form',
116
+ mapUrl: 'mod-form/form/homeowner.min.js.map'
117
+ },
118
+ srcReplaceFn: replaceFootAssetScripts,
119
+ additionalSrcReplaceFns: []
120
+ },
121
+ copyModalytics: {
122
+ url: 'mod-alytics/modalytics.min.js',
123
+ config: {
124
+ fileName: 'modAlyticsFileName',
125
+ dest: 'scripts/mod-alytics',
126
+ mapUrl: 'mod-alytics/modalytics.min.js.map'
127
+ },
128
+ srcReplaceFn: replaceModalyticsSrc,
129
+ additionalSrcReplaceFns: []
130
+ },
131
+ copyAbandonmentComponentStyles: {
132
+ url: 'shared-resources/styles/components/abandonment/abandonment.min.css',
133
+ config: {
134
+ fileName: 'abandonmentStylesFileName',
135
+ dest: 'styles/components/abandonment',
136
+ mapUrl: null
137
+ },
138
+ srcReplaceFn: null,
139
+ additionalSrcReplaceFns: []
140
+ },
141
+ copyAbandonmentJs: {
142
+ url: 'shared-resources/scripts/abandonment/abandonment.min.js',
143
+ config: {
144
+ fileName: 'abandonmentJsFileName',
145
+ dest: 'scripts/abandonment',
146
+ mapUrl: 'shared-resources/scripts/abandonment/abandonment.min.js.map'
147
+ },
148
+ srcReplaceFn: replaceAbandonmentJsCssSrc,
149
+ additionalSrcReplaceFns: []
150
+ },
151
+ copyModFooterComponentStyles: {
152
+ url: 'shared-resources/styles/components/footer/mod-footer.min.css',
153
+ config: {
154
+ fileName: 'modFooterStylesFileName',
155
+ dest: 'styles/components/footer',
156
+ mapUrl: null
157
+ },
158
+ srcReplaceFn: null,
159
+ additionalSrcReplaceFns: []
160
+ },
161
+ copyQsFooterComponentStyles: {
162
+ url: 'shared-resources/styles/components/footer/qs-footer.min.css',
163
+ config: {
164
+ fileName: 'qsFooterStylesFileName',
165
+ dest: 'styles/components/footer',
166
+ mapUrl: null
167
+ },
168
+ srcReplaceFn: null,
169
+ additionalSrcReplaceFns: [replaceFooterStylesReference, replaceFooterStylesReferenceInMap]
170
+ }
171
+ };
172
+
173
+ function getResource(task, fileNames, resourcePath = 'quote/resources') {
174
+ const { url, config, srcReplaceFn, additionalSrcReplaceFns } = task;
175
+
176
+ if (Object.keys(config).length === 0) {
177
+ return false;
178
+ }
179
+
180
+ const finished = promisify(stream.finished);
181
+
182
+ return new Promise(resolve => {
183
+ const file = getFileFromURL(url);
184
+
185
+ if (!fs.existsSync(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}`)) {
186
+ fs.mkdirSync(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}`, { recursive: true });
187
+ }
188
+
189
+ // if file exists, do not create it again
190
+ if (fs.existsSync(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}/${file}`)) {
191
+ resolve();
192
+ } else {
193
+ const options = {
194
+ url: `https://${task.config.defaultSettings.resourceDomain}/${resourcePath}/${url}`,
195
+ method: 'get',
196
+ responseType: 'stream'
197
+ }
198
+ axios(options).then(resp => {
199
+ if (resp.status !== 200) {
200
+ throw new Error(`${resp.status}: Error while fetching ${url}`);
201
+ }
202
+
203
+ const writer = createWriteStream(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}/${file}`);
204
+ resp.data.pipe(writer);
205
+ console.log(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}/${file} created...`);
206
+ return finished(writer);
207
+ })
208
+ .then(() => {
209
+ gulp.src(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}/${file}`)
210
+ .pipe(hash({
211
+ hashLength: 20,
212
+ algorithm: 'md5',
213
+ template: file.replace(/^([^.]*)\.(.*)$/, '$1-<%= hash %>.$2')
214
+ }))
215
+ .pipe(tap(function(file, t) {
216
+ file = JSON.stringify(file);
217
+ file = JSON.parse(file).history[1];
218
+ fileNames[task.config.fileName] = file.split('/').pop();
219
+ }))
220
+ .pipe(gulp.dest(`${task.config.defaultSettings.srcFolder}/resources/${config.dest}`));
221
+ resolve();
222
+ })
223
+ .then(() => {
224
+ if (!config.mapUrl) {
225
+ return false;
226
+ }
227
+ // do we really need to separately get sourcemaps??
228
+ resolve();
229
+ })
230
+ .then(() => {
231
+ if (!srcReplaceFn) {
232
+ return false;
233
+ }
234
+ // we should update the mod/qs footer components to inject their own CSS instead of hardcoding the file path & then renaming it here!
235
+ resolve();
236
+ })
237
+ }
238
+ })
239
+ }
240
+
241
+ export default async function(done) {
242
+ const { isLocal } = defaultSettings;
243
+ const isQuotePage = siteData?.siteData?.isQuotePage || siteData?.isQuotePage;
244
+ const useAccessibleComponents = siteData?.siteData?.useAccessibleConfig || siteData?.useAccessibleConfig;
245
+ const useRelativePathForResources = siteData?.siteData?.useRelativePathForResources || siteData?.useRelativePathForResources;
246
+ componentFolderPath = useAccessibleComponents === true ? 'accessible-components' : 'shared-components';
247
+ isQuotePageOrUseRelativePath = isQuotePage === true || useRelativePathForResources === true;
248
+ const isPathSubdirectory = siteData?.siteData?.pathSubdirectory || siteData?.pathSubdirectory;
249
+ pathSubdirectory = !isLocal && isPathSubdirectory ? isPathSubdirectory : '';
250
+
251
+ const tasks = Object.values(TASKS);
252
+ if (tasks.length) {
253
+ const getAllResources = tasks.map(async function(task) {
254
+ if (useAccessibleComponents === true) {
255
+ if (task.url.includes('abandonment.min.js')) {
256
+ task.url = 'shared-resources/scripts/abandonment/accessible/abandonment.min.js';
257
+ task.config.mapUrl = 'shared-resources/scripts/abandonment/accessible/abandonment.min.js.map';
258
+ }
259
+ }
260
+ Object.assign(task.config, { defaultSettings, siteData });
261
+ await getResource(task, fileNames);
262
+ });
263
+
264
+ await Promise.all(getAllResources);
265
+ done();
266
+ }
267
+ }
package/tasks/serve.js ADDED
@@ -0,0 +1,15 @@
1
+ // import { task } from 'gulp';
2
+ import gulp from 'gulp';
3
+ import grabSharedComponents from './grab-shared-components.js';
4
+ import grabSharedScripts from './grab-shared-scripts.js';
5
+ import clean from './clean.js';
6
+ import grabCdn from './grab-cdn.js';
7
+ import grabFormHelpers from './grab-form-helpers.js';
8
+ import templates from './templates.js';
9
+
10
+ export function done() {
11
+ console.log('done');
12
+ }
13
+
14
+ // Define a gulp task to test if gulp is running correctly
15
+ export default gulp.series(clean, grabCdn, grabSharedComponents, grabSharedScripts, grabFormHelpers, templates, done);