amphora-html 6.0.0-1 → 6.0.0-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.
Files changed (87) hide show
  1. package/.envrc +1 -1
  2. package/lib/media.js +7 -22
  3. package/lib/media.test.js +112 -1
  4. package/package.json +2 -1
  5. package/.vscode/.history/amphora-html/lib/media_20210422170004.js +0 -418
  6. package/.vscode/.history/amphora-html/lib/media_20210423114100.js +0 -419
  7. package/.vscode/.history/amphora-html/lib/media_20210423114125.js +0 -420
  8. package/.vscode/.history/amphora-html/lib/media_20210423121821.js +0 -420
  9. package/.vscode/.history/amphora-html/lib/media_20210423121839.js +0 -420
  10. package/.vscode/.history/amphora-html/lib/media_20210423133939.js +0 -420
  11. package/.vscode/.history/amphora-html/lib/media_20210423143343.js +0 -420
  12. package/.vscode/.history/amphora-html/lib/media_20210423143445.js +0 -420
  13. package/.vscode/.history/amphora-html/lib/media_20210430141402.js +0 -423
  14. package/.vscode/.history/amphora-html/lib/media_20210430142038.js +0 -432
  15. package/.vscode/.history/amphora-html/lib/media_20210430142153.js +0 -434
  16. package/.vscode/.history/amphora-html/lib/media_20210430142400.js +0 -434
  17. package/.vscode/.history/amphora-html/lib/media_20210430142437.js +0 -436
  18. package/.vscode/.history/amphora-html/lib/media_20210430142934.js +0 -436
  19. package/.vscode/.history/amphora-html/lib/media_20210430143110.js +0 -437
  20. package/.vscode/.history/amphora-html/lib/media_20210430143347.js +0 -441
  21. package/.vscode/.history/amphora-html/lib/media_20210430143354.js +0 -441
  22. package/.vscode/.history/amphora-html/lib/media_20210430143517.js +0 -442
  23. package/.vscode/.history/amphora-html/lib/media_20210430143831.js +0 -446
  24. package/.vscode/.history/amphora-html/lib/media_20210430144135.js +0 -446
  25. package/.vscode/.history/amphora-html/lib/media_20210430144206.js +0 -447
  26. package/.vscode/.history/amphora-html/lib/media_20210430144435.js +0 -458
  27. package/.vscode/.history/amphora-html/lib/media_20210503102940.js +0 -449
  28. package/.vscode/.history/amphora-html/lib/media_20210503103055.js +0 -435
  29. package/.vscode/.history/amphora-html/lib/media_20210503105800.js +0 -435
  30. package/.vscode/.history/amphora-html/lib/media_20210503115000.js +0 -435
  31. package/.vscode/.history/amphora-html/lib/media_20210503120729.js +0 -455
  32. package/.vscode/.history/amphora-html/lib/media_20210503120737.js +0 -455
  33. package/.vscode/.history/amphora-html/lib/media_20210503120859.js +0 -455
  34. package/.vscode/.history/amphora-html/lib/media_20210503121446.js +0 -455
  35. package/.vscode/.history/amphora-html/lib/media_20210503123023.js +0 -455
  36. package/.vscode/.history/amphora-html/lib/media_20210503123146.js +0 -435
  37. package/.vscode/.history/amphora-html/lib/media_20210503123207.js +0 -435
  38. package/.vscode/.history/amphora-html/lib/media_20210503123232.js +0 -458
  39. package/.vscode/.history/amphora-html/lib/media_20210503123433.js +0 -435
  40. package/.vscode/.history/amphora-html/lib/media_20210503124026.js +0 -435
  41. package/.vscode/.history/amphora-html/lib/media_20210503124152.js +0 -444
  42. package/.vscode/.history/amphora-html/lib/media_20210503124256.js +0 -455
  43. package/.vscode/.history/amphora-html/lib/media_20210503124650.js +0 -462
  44. package/.vscode/.history/amphora-html/lib/media_20210503124855.js +0 -453
  45. package/.vscode/.history/amphora-html/lib/media_20210503130202.js +0 -453
  46. package/.vscode/.history/amphora-html/lib/media_20210503130230.js +0 -453
  47. package/.vscode/.history/amphora-html/lib/media_20210503130932.js +0 -456
  48. package/.vscode/.history/amphora-html/lib/media_20210503131700.js +0 -457
  49. package/.vscode/.history/amphora-html/lib/media_20210503131800.js +0 -457
  50. package/.vscode/.history/amphora-html/lib/media_20210503131943.js +0 -457
  51. package/.vscode/.history/amphora-html/lib/media_20210503132029.js +0 -457
  52. package/.vscode/.history/amphora-html/lib/media_20210503135814.js +0 -457
  53. package/.vscode/.history/amphora-html/lib/media_20210503140648.js +0 -457
  54. package/.vscode/.history/amphora-html/lib/media_20210503161154.js +0 -427
  55. package/.vscode/.history/amphora-html/lib/media_20210503161242.js +0 -427
  56. package/.vscode/.history/amphora-html/lib/media_20210503165324.js +0 -427
  57. package/.vscode/.history/amphora-html/lib/media_20210503171517.js +0 -427
  58. package/.vscode/.history/amphora-html/lib/media_20210503173501.js +0 -427
  59. package/.vscode/.history/amphora-html/lib/media_20210504114616.js +0 -427
  60. package/.vscode/.history/amphora-html/lib/media_20210504121950.js +0 -427
  61. package/.vscode/.history/amphora-html/lib/media_20210504122005.js +0 -427
  62. package/.vscode/.history/amphora-html/lib/media_20210504122119.js +0 -427
  63. package/.vscode/.history/amphora-html/lib/media_20210504122215.js +0 -427
  64. package/.vscode/.history/amphora-html/lib/media_20210504161319.js +0 -427
  65. package/.vscode/.history/amphora-html/lib/media_20210504163440.js +0 -427
  66. package/.vscode/.history/amphora-html/lib/media_20210505105706.js +0 -427
  67. package/.vscode/.history/amphora-html/lib/media_20210505112458.js +0 -427
  68. package/.vscode/.history/amphora-html/lib/media_20210511135806.js +0 -434
  69. package/.vscode/.history/amphora-html/lib/media_20210512105948.js +0 -434
  70. package/.vscode/.history/amphora-html/lib/media_20210512110245.js +0 -434
  71. package/.vscode/.history/amphora-html/lib/media_20210512114913.js +0 -434
  72. package/.vscode/.history/amphora-html/lib/media_20210512114917.js +0 -434
  73. package/.vscode/.history/amphora-html/lib/media_20210512122725.js +0 -429
  74. package/.vscode/.history/amphora-html/lib/media_20210512123057.js +0 -429
  75. package/.vscode/.history/amphora-html/lib/media_20210512123102.js +0 -429
  76. package/.vscode/.history/amphora-html/lib/media_20210512123201.js +0 -429
  77. package/.vscode/.history/amphora-html/lib/media_20210512152244.js +0 -429
  78. package/.vscode/.history/amphora-html/lib/media_20210512152536.js +0 -433
  79. package/.vscode/.history/amphora-html/lib/media_20210512152541.js +0 -433
  80. package/.vscode/.history/amphora-html/lib/media_20210512152717.js +0 -433
  81. package/.vscode/.history/amphora-html/lib/media_20210512152931.js +0 -419
  82. package/.vscode/.history/amphora-html/lib/media_20210512152949.js +0 -420
  83. package/.vscode/.history/amphora-html/lib/media_20210512152958.js +0 -418
  84. package/.vscode/.history/amphora-html/lib/media_20210512155619.js +0 -418
  85. package/.vscode/.history/amphora-html/lib/media_20210512164028.js +0 -418
  86. package/.vscode/.history/amphora-html/lib/media_20210512170157.js +0 -418
  87. package/.vscode/.history/amphora-html/lib/media_20210512171030.js +0 -418
package/.envrc CHANGED
@@ -1,2 +1,2 @@
1
- use node 12
1
+ use node 14
2
2
  layout node
package/lib/media.js CHANGED
@@ -6,6 +6,7 @@ const _ = require('lodash'),
6
6
  bluebird = require('bluebird'),
7
7
  setup = require('./setup'),
8
8
  styleguide = require('./styleguide'),
9
+ url = require('url'),
9
10
  STYLE_TAG = 'style',
10
11
  SCRIPT_TAG = 'scripts',
11
12
  ASYNC_SCRIPT_TAG = 'async',
@@ -331,15 +332,10 @@ function getManifestAssets(state) {
331
332
  return [];
332
333
  }
333
334
 
334
- const runtime = _.get(manifest, 'runtime.js', '');
335
+ const entrypoints = _.get(manifest, 'entrypoints', []);
336
+ const scriptFiles = _.flatMap(entrypoints, entrypoint => _.get(entrypoint, 'assets.js', []));
335
337
 
336
- const scriptFiles = [...state._components, '__clay_globals', '__clay_client_init'].reduce((components, component) => {
337
- const assets = _.get(manifest, ['entrypoints', component, 'assets', 'js'], []);
338
-
339
- return components.concat(assets);
340
- }, []);
341
-
342
- return _.union(runtime, scriptFiles).map(script => path.join(assetHost, script));
338
+ return scriptFiles.map(script => url.resolve(assetHost, script));
343
339
  }
344
340
 
345
341
  /**
@@ -412,28 +408,17 @@ function injectScriptsAndStyles(state) {
412
408
 
413
409
  if (!locals.edit) {
414
410
  mediaMap.styles = combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
415
- mediaMap.scripts = combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
416
-
417
- // TODO: Ideally, we'd load these scripts asynchronously or after the DOM
418
- // is ready, setting the `async` attribute, the `defer` attribute, or
419
- // both. Because the order in which they're parsed and executed currently
420
- // matters, we can't do that safely.
421
- mediaMap.manifestAssets = injectTags(mediaMap.manifestAssets, locals.site, SCRIPT_TAG);
411
+ mediaMap.scripts = !!mediaMap.manifestAssets && mediaMap.manifestAssets.length > 0
412
+ ? injectTags(mediaMap.manifestAssets, locals.site, ASYNC_SCRIPT_TAG)
413
+ : combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
422
414
  } else {
423
415
  mediaMap.styles = module.exports.editStylesTags ? injectTags(mediaMap.styles, locals.site, STYLE_TAG) : combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
424
416
  mediaMap.scripts = module.exports.editScriptsTags ? injectTags(mediaMap.scripts, locals.site, SCRIPT_TAG) : combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
425
-
426
- // FIXME: Some of the logic which excludes client-side scripts from edit
427
- // mode sits with nymag/sites, in the `resolve-media` module, and some
428
- // lives here. Since we're currently not using Webpack for Kiln and model
429
- // assets, this feels like the best place to null out client scripts.
430
- mediaMap.manifestAssets = null;
431
417
  }
432
418
 
433
419
  return bluebird.props(mediaMap)
434
420
  .then(combinedFiles => {
435
421
  html = combinedFiles.styles ? appendMediaToTop(combinedFiles.styles, html) : html; // If there are styles, append them
436
- html = combinedFiles.manifestAssets ? appendMediaToBottom(combinedFiles.manifestAssets, html) : html; // If there are assets registered with the manifest, append them
437
422
  html = combinedFiles.scripts ? appendMediaToBottom(combinedFiles.scripts, html) : html; // If there are scripts, append them
438
423
  return html; // Return the compiled HTML
439
424
  });
package/lib/media.test.js CHANGED
@@ -11,7 +11,7 @@ const _ = require('lodash'),
11
11
  jest.mock('nymag-fs', () => ({
12
12
  fileExists: () => false,
13
13
  readFilePromise: () => Promise.resolve(''),
14
- tryRequire: () => undefined
14
+ tryRequire: () => ({})
15
15
  }));
16
16
 
17
17
  describe(_.startCase(filename), () => {
@@ -625,6 +625,117 @@ describe(_.startCase(filename), () => {
625
625
  );
626
626
  });
627
627
 
628
+ describe('getManifestAssets', () => {
629
+ const fn = lib['getManifestAssets'];
630
+
631
+ describe('constructs the correct asset URL', () => {
632
+ test('when assetHost is configured', () => {
633
+ const assetHost = 'https://assets.nymag.com';
634
+ const localState = {
635
+ locals: {
636
+ site: {
637
+ assetHost
638
+ }
639
+ },
640
+ _components: [
641
+ 'a',
642
+ 'b'
643
+ ]
644
+ };
645
+ const manifest = {
646
+ entrypoints: {
647
+ a: {
648
+ assets: {
649
+ js: ['/a.js']
650
+ }
651
+ },
652
+ b: {
653
+ assets: {
654
+ js: ['b.js']
655
+ }
656
+ }
657
+ }
658
+ };
659
+
660
+ jest.spyOn(files, 'tryRequire').mockImplementation(() => manifest);
661
+
662
+ expect(fn(localState)).toEqual([
663
+ `${ assetHost }/a.js`,
664
+ `${ assetHost }/b.js`
665
+ ]);
666
+ });
667
+
668
+ test('when assetHost is not configured', () => {
669
+ const localState = {
670
+ locals: {
671
+ site: {
672
+ }
673
+ },
674
+ _components: [
675
+ 'a',
676
+ 'b'
677
+ ]
678
+ };
679
+ const manifest = {
680
+ entrypoints: {
681
+ a: {
682
+ assets: {
683
+ js: ['/a.js']
684
+ }
685
+ },
686
+ b: {
687
+ assets: {
688
+ js: ['b.js']
689
+ }
690
+ }
691
+ }
692
+ };
693
+
694
+ jest.spyOn(files, 'tryRequire').mockImplementation(() => manifest);
695
+
696
+ expect(fn(localState)).toEqual([
697
+ '/a.js',
698
+ '/b.js'
699
+ ]);
700
+ });
701
+
702
+ test('without prepending assetPath', () => {
703
+ const localState = {
704
+ locals: {
705
+ site: {
706
+ assetPath: '/strategist'
707
+ }
708
+ },
709
+ _components: [
710
+ 'a',
711
+ 'b'
712
+ ]
713
+ };
714
+ const manifest = {
715
+ entrypoints: {
716
+ a: {
717
+ assets: {
718
+ js: ['/a.js']
719
+ }
720
+ },
721
+ b: {
722
+ assets: {
723
+ js: ['b.js']
724
+ }
725
+ }
726
+ }
727
+ };
728
+
729
+ jest.spyOn(files, 'tryRequire').mockImplementation(() => manifest);
730
+
731
+ expect(fn(localState)).toEqual([
732
+ '/a.js',
733
+ '/b.js'
734
+ ]);
735
+ });
736
+ });
737
+ });
738
+
628
739
  describe('injectScriptsAndStyles', () => {
629
740
  const fn = lib['injectScriptsAndStyles'];
630
741
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amphora-html",
3
- "version": "6.0.0-1",
3
+ "version": "6.0.0-5",
4
4
  "description": "An HTML renderer for component data",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -20,6 +20,7 @@
20
20
  "traverse": "^0.6.6"
21
21
  },
22
22
  "devDependencies": {
23
+ "clayhandlebars": "^5.0.1",
23
24
  "coveralls": "^3.0.2",
24
25
  "eslint": "^3.19.0",
25
26
  "jest": "23.6.0"
@@ -1,418 +0,0 @@
1
- 'use strict';
2
-
3
- const _ = require('lodash'),
4
- path = require('path'),
5
- files = require('nymag-fs'),
6
- bluebird = require('bluebird'),
7
- setup = require('./setup'),
8
- styleguide = require('./styleguide'),
9
- STYLE_TAG = 'style',
10
- SCRIPT_TAG = 'scripts',
11
- MEDIA_DIRECTORY = path.join(process.cwd(), 'public');
12
-
13
- /**
14
- * @param {string} str
15
- * @returns {number}
16
- */
17
- function findBottom(str) {
18
- var index = str.lastIndexOf('</body>');
19
-
20
- if (index === -1) {
21
- index = str.lastIndexOf('</');
22
- }
23
-
24
- return index;
25
- }
26
-
27
- /**
28
- * @param {string} str
29
- * @returns {number}
30
- */
31
- function findTop(str) {
32
- var index = str.indexOf('</head>');
33
-
34
- if (index === -1) {
35
- index = str.indexOf('>') + 1;
36
- }
37
- return index;
38
- }
39
-
40
- /**
41
- * Put items at index in the very large target string.
42
- *
43
- * @param {string} str
44
- * @param {number} index
45
- * @param {[string]} items
46
- * @returns {string}
47
- */
48
- function splice(str, index, items) {
49
- return str.substr(0, index) + items + str.substr(index);
50
- }
51
-
52
- /**
53
- * Get the contents of a string that come after specified characters.
54
- *
55
- * @param {string} str Any string to split
56
- * @param {string} dir The directory the file is in
57
- * @return {string}
58
- */
59
- function getFileName(str, dir) {
60
- return str.split(dir)[1];
61
- }
62
-
63
- /**
64
- * Retrieve the contents of a file
65
- *
66
- * @param {array} fileArray An array of file names
67
- * @param {string} targetDir The directory to retrieve files from
68
- * @param {string} filePrefix The string that comes right before the file name
69
- * @return {Promise}
70
- */
71
- function getContentsOfFiles(fileArray, targetDir, filePrefix) {
72
- var allPromises = [],
73
- currentDir = process.cwd();
74
-
75
- fileArray.forEach(file => {
76
- allPromises.push(files.readFilePromise(path.join(currentDir, targetDir, getFileName(file, filePrefix))));
77
- });
78
-
79
- return Promise.all(allPromises)
80
- .catch(err => {
81
- throw err;
82
- });
83
- }
84
-
85
- /**
86
- * Wraps a string with HTML tags
87
- * @param {string} string The string to wrap
88
- * @param {string} tag The HTML tag to use
89
- * @return {string}
90
- */
91
- function wrapWithTags(string, tag) {
92
- if (tag === SCRIPT_TAG) {
93
- return `<script type="text/javascript">
94
- // <![CDATA[
95
- ${string}
96
- // ]]
97
- </script>`;
98
- } else {
99
- return `<style>${string}</style>`;
100
- }
101
- }
102
-
103
- /**
104
- * Concatenates an array of files into one string.
105
- *
106
- * @param {array} fileArray An array of files
107
- * @param {string} directory The directory in which `fs` will look for the file
108
- * @param {string} filePrefix The directory path before the filename
109
- * @param {string|null} tag The type of tag to wrap the contents in.
110
- * @return {string}
111
- */
112
- function combineFileContents(fileArray, directory, filePrefix, tag) {
113
- if (!fileArray || !fileArray.length) {
114
- return false;
115
- }
116
-
117
- // If there are files, retrieve contents
118
- return getContentsOfFiles(fileArray, directory, filePrefix)
119
- .then(function (fileContents) {
120
- return wrapWithTags(fileContents.join(''), tag);
121
- });
122
- }
123
-
124
- /**
125
- * Append at the bottom of the head tag, or if no head tag, then the top of root tag.
126
- *
127
- * @param {array} styles
128
- * @param {string} html
129
- * @returns {string}
130
- */
131
- function appendMediaToTop(styles, html) {
132
- var index = findTop(html);
133
-
134
- return splice(html, index, styles);
135
- }
136
-
137
- /**
138
- * Append at the bottom of the body tag, or if no body tag, then the bottom of the root tag.
139
- * @param {Array} scripts
140
- * @param {string} html
141
- * @returns {string}
142
- */
143
- function appendMediaToBottom(scripts, html) {
144
- var index = findBottom(html);
145
-
146
- return splice(html, index, scripts);
147
- }
148
-
149
- function injectTags(fileArray, site, tag) {
150
- var buster = module.exports.cacheBuster ? `?version=${module.exports.cacheBuster}` : '';
151
-
152
- return bluebird.resolve(_.map(fileArray, function (file) {
153
- if (tag === STYLE_TAG) {
154
- return `<link rel="stylesheet" type="text/css" href="${file}${buster}">`;
155
- } else {
156
- return `<script defer type="text/javascript" src="${file}${buster}"></script>`;
157
- }
158
- }).join('\n'));
159
- }
160
-
161
- /**
162
- * Gets a list of all css and js needed for the components listed.
163
- * @param {Object} state
164
- * @returns {{styles: Array, scripts: Array}}
165
- */
166
- function getMediaMap(state) {
167
- return {
168
- packs: module.exports.getManifestScripts(state),
169
- styles: module.exports.getStyleFiles(state),
170
- scripts: module.exports.getScriptFiles(state)
171
- };
172
- }
173
-
174
- /* eslint-disable complexity */
175
- /**
176
- * Get the proper styles for the component. If a styleguide is configured, use
177
- * that css. Defaults to the site slug
178
- *
179
- * @param {Object} state
180
- * @returns {array}
181
- */
182
- function getStyleFiles(state) {
183
- const { site } = state.locals,
184
- assetDir = site && site.assetDir || MEDIA_DIRECTORY,
185
- assetPath = site && site.assetPath || '',
186
- assetHost = site && site.assetHost || '',
187
- siteStyleguide = site && site.styleguide,
188
- layoutName = _.get(state, '_layoutData.name');
189
- let cssFilePaths = [], layoutBasePath;
190
-
191
- // legacy behavior: load <component>.css and <component>.<site>.css
192
- if (!site.styleguide) {
193
- const siteSlug = site && site.slug;
194
-
195
- cssFilePaths = state._components
196
- .reduce((acc, curr) => {
197
- acc.push(
198
- path.join(assetDir, 'css', `${curr}.css`),
199
- path.join(assetDir, 'css', `${curr}.${siteSlug}.css`)
200
- );
201
- return acc;
202
- }, []);
203
- // in edit mode, grab all variations
204
- } else if (state.locals.edit) {
205
- const availableVariations = styleguide.getVariations(siteStyleguide);
206
-
207
- cssFilePaths = state._components
208
- .reduce((acc, cmptName) => {
209
- acc.push(cmptName, ...availableVariations[cmptName] || []);
210
- return acc;
211
- }, [])
212
- .map(baseName => {
213
- const basePath = path.join(assetDir, 'css', `${baseName}.${siteStyleguide}.css`);
214
-
215
- return files.fileExists(basePath) ?
216
- basePath :
217
- path.join(assetDir, 'css', `${baseName}._default.css`);
218
- });
219
- // in view mode, grab only used variations
220
- } else if (state._usedVariations) {
221
- cssFilePaths = state._usedVariations
222
- .map(variation => {
223
- const styleguideVariationPath = path.join(assetDir, 'css', `${variation}.${siteStyleguide}.css`);
224
-
225
- return files.fileExists(styleguideVariationPath) ?
226
- styleguideVariationPath :
227
- path.join(assetDir, 'css', `${variation}._default.css`);
228
- });
229
- }
230
-
231
- // add the layout css
232
- if (layoutName) {
233
- layoutBasePath = path.join(assetDir, 'css', `${layoutName}.${siteStyleguide}.css`);
234
-
235
- if (files.fileExists(layoutBasePath)) {
236
- cssFilePaths.push(layoutBasePath);
237
- } else {
238
- cssFilePaths.push(path.join(assetDir, 'css', `${layoutName}._default.css`));
239
- }
240
- }
241
-
242
- return cssFilePaths
243
- .filter(files.fileExists)
244
- .map(pathJoin(assetHost, assetPath, assetDir));
245
- }
246
- /* eslint-enable complexity */
247
-
248
- /**
249
- * Get the proper scripts for the component
250
- *
251
- * @param {string} name
252
- * @param {object} site
253
- * @returns {array}
254
- */
255
-
256
- function getScriptFiles(state) {
257
- const site = state.locals.site,
258
- slug = site.slug,
259
- assetDir = site && site.assetDir || MEDIA_DIRECTORY,
260
- assetPath = site && site.assetPath || '',
261
- assetHost = site && site.assetHost || '';
262
-
263
- return state._components
264
- .reduce((prev, name) => {
265
- prev.push(
266
- path.join(assetDir, 'js', `${name}.js`),
267
- path.join(assetDir, 'js', `${name}.${slug}.js`),
268
- path.join(assetDir, 'js', `${name}.client.js`)
269
- );
270
- return prev;
271
- }, [])
272
- .filter(files.fileExists)
273
- .map(pathJoin(assetHost, assetPath, assetDir));
274
- }
275
-
276
- /**
277
- * Read the asset manifest generated by the `clay pack` bundling command and
278
- * check for scripts which match the rendered component names. The manifest for
279
- * each asset lists its complete set of dependencies, so we dedupe them, then
280
- * move the components' scripts to the end of the list and the Webpack runtime
281
- * to the beginning.
282
- *
283
- * @async
284
- * @param {Object} state - Amphora's render state.
285
- * @return {Promise<string[]>} A list of component assets.
286
- */
287
- function getManifestScripts(state) {
288
- const site = state.locals.site,
289
- assetDir = site && site.assetDir || MEDIA_DIRECTORY,
290
- assetHost = site && site.assetHost || '/',
291
- manifestName = site && site.manifestName || 'assets-manifest.json',
292
- manifestFile = path.resolve(path.join(assetDir, manifestName)),
293
- manifest = files.tryRequire(manifestFile);
294
-
295
- if (!manifest) return [];
296
-
297
- const scripts = state._components.reduce((acc, component) => {
298
- const allDependencies = _.get(manifest, ['entrypoints', component, 'assets', 'js'], []),
299
- componentScript = allDependencies.find(script => script.includes(component)),
300
- dependencyScripts = _.without(allDependencies, componentScript);
301
-
302
- acc.components = acc.components.concat(componentScript);
303
- acc.dependencies = _.union(acc.dependencies, dependencyScripts);
304
- return acc;
305
- }, {
306
- components: [],
307
- dependencies: [],
308
- });
309
-
310
- const runtimeFile = _.get(manifest, 'runtime.js'),
311
- dependenciesWithoutRuntime = _.without(scripts.dependencies, runtimeFile),
312
- combinedScripts = [
313
- runtimeFile,
314
- ...dependenciesWithoutRuntime,
315
- ...scripts.components
316
- ].filter(Boolean);
317
-
318
- return combinedScripts.map(script => path.join(assetHost, script));
319
- }
320
-
321
- /**
322
- * Trim the path on the file system bythe link of the
323
- * asset directory and then join it with either the assetHost
324
- * value of the site or the assetPath value (found in the
325
- * site's config file)
326
- *
327
- * @param {String} assetHost
328
- * @param {String} assetPath
329
- * @param {String} assetDir
330
- * @return {Function}
331
- */
332
- function pathJoin(assetHost, assetPath, assetDir) {
333
- var assetDirLen = assetDir.length;
334
-
335
- return function (filePath) {
336
- var pathToFile = filePath.substr(assetDirLen);
337
-
338
- if (assetHost) return `${assetHost}${pathToFile}`;
339
- return path.join(assetPath, pathToFile);
340
- };
341
- }
342
-
343
- /**
344
- * Set the values for inlining vs tagging edit mode styles/scripts
345
- *
346
- * @param {object|boolean} options
347
- * @param {string} [cacheBuster]
348
- */
349
- function configure(options, cacheBuster = '') {
350
- if (options && _.isObject(options)) {
351
- module.exports.editStylesTags = options.styles || false;
352
- module.exports.editScriptsTags = options.scripts || false;
353
- } else {
354
- module.exports.editStylesTags = options;
355
- module.exports.editScriptsTags = options;
356
- }
357
- // Assign cacheBuster
358
- module.exports.cacheBuster = cacheBuster;
359
- }
360
-
361
- /**
362
- * Given the state and html string...
363
- *
364
- * 1. Find all associated scripts/styles
365
- * 2. Run `resolveMedia`
366
- * 3. Stitch in the assets' contents
367
- * 4. Return the HTML string
368
- *
369
- * @param {Object} state
370
- * @return {Function}
371
- */
372
- function injectScriptsAndStyles(state) {
373
- const { locals } = state;
374
-
375
- return function (html) {
376
- var mediaMap = {};
377
-
378
- // Check that HTML is string
379
- if (typeof html !== 'string') {
380
- throw new Error('Missing html parameter');
381
- }
382
-
383
- // We've got a string so let's actually get the map of styles
384
- mediaMap = module.exports.getMediaMap(state);
385
-
386
- // allow site to change the media map before applying it
387
- if (setup.resolveMedia) mediaMap = setup.resolveMedia(mediaMap, locals) || mediaMap;
388
- mediaMap.packs = injectTags(mediaMap.packs, locals.site, SCRIPT_TAG);
389
-
390
- if (!locals.edit) {
391
- mediaMap.styles = combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
392
- mediaMap.scripts = combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
393
- } else {
394
- mediaMap.styles = module.exports.editStylesTags ? injectTags(mediaMap.styles, locals.site, STYLE_TAG) : combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
395
- mediaMap.scripts = module.exports.editScriptsTags ? injectTags(mediaMap.scripts, locals.site, SCRIPT_TAG) : combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
396
- }
397
-
398
- return bluebird.props(mediaMap)
399
- .then(combinedFiles => {
400
- html = combinedFiles.styles ? appendMediaToTop(combinedFiles.styles, html) : html; // If there are styles, append them
401
- html = combinedFiles.scripts ? appendMediaToBottom(combinedFiles.scripts, html) : html; // If there are scripts, append them
402
- html = combinedFiles.packs ? appendMediaToBottom(combinedFiles.packs, html) : html; // If there are packs, append them
403
- return html; // Return the compiled HTML
404
- });
405
- };
406
- }
407
-
408
- module.exports.injectScriptsAndStyles = injectScriptsAndStyles;
409
- module.exports.getMediaMap = getMediaMap;
410
- module.exports.cacheBuster = '';
411
- module.exports.configure = configure;
412
- module.exports.editStylesTags = false;
413
- module.exports.editScriptsTags = false;
414
-
415
- // For testing
416
- module.exports.getManifestScripts = getManifestScripts;
417
- module.exports.getScriptFiles = getScriptFiles;
418
- module.exports.getStyleFiles = getStyleFiles;