amphora-html 6.0.0-8 → 6.0.0
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/.github/workflows/ci.yml +40 -0
- package/lib/media.js +69 -83
- package/lib/media.test.js +4 -115
- package/lib/render.js +12 -5
- package/package.json +4 -1
- package/.circleci/config.yml +0 -44
- package/.github/workflows/push.yml +0 -26
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ['**']
|
|
6
|
+
tags: ['**']
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
name: Test (Node ${{ matrix.node-version }})
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
node-version: [20]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
29
|
+
uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: ${{ matrix.node-version }}
|
|
32
|
+
cache: npm
|
|
33
|
+
cache-dependency-path: package-lock.json
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: npm ci
|
|
37
|
+
|
|
38
|
+
- name: Run tests
|
|
39
|
+
run: npm test
|
|
40
|
+
|
package/lib/media.js
CHANGED
|
@@ -6,12 +6,10 @@ const _ = require('lodash'),
|
|
|
6
6
|
bluebird = require('bluebird'),
|
|
7
7
|
setup = require('./setup'),
|
|
8
8
|
styleguide = require('./styleguide'),
|
|
9
|
-
url = require('url'),
|
|
10
9
|
STYLE_TAG = 'style',
|
|
11
10
|
SCRIPT_TAG = 'scripts',
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
ASYNC_DEFER_SCRIPT_TAG = 'async-defer',
|
|
11
|
+
MODULE_SCRIPT_TAG = 'module',
|
|
12
|
+
MODULEPRELOAD_TAG = 'modulepreload',
|
|
15
13
|
MEDIA_DIRECTORY = path.join(process.cwd(), 'public');
|
|
16
14
|
|
|
17
15
|
/**
|
|
@@ -150,47 +148,36 @@ function appendMediaToBottom(scripts, html) {
|
|
|
150
148
|
return splice(html, index, scripts);
|
|
151
149
|
}
|
|
152
150
|
|
|
153
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Build inline <link>/<script> tags for an array of asset paths. Used by edit
|
|
153
|
+
* mode (where assets are loaded individually rather than bundled) and by the
|
|
154
|
+
* Vite ESM pipeline (module / modulepreload).
|
|
155
|
+
*
|
|
156
|
+
* @param {string[]} fileArray asset paths
|
|
157
|
+
* @param {string} tag one of STYLE_TAG, SCRIPT_TAG, MODULE_SCRIPT_TAG, MODULEPRELOAD_TAG
|
|
158
|
+
* @returns {Promise<string>} newline-joined tag string
|
|
159
|
+
*/
|
|
160
|
+
function injectTags(fileArray, tag) {
|
|
154
161
|
var buster = module.exports.cacheBuster ? `?version=${module.exports.cacheBuster}` : '';
|
|
162
|
+
// When omitCacheBusterOnModules is enabled, content-hashed ESM files omit the
|
|
163
|
+
// ?version= query string — the hash in the filename already provides cache busting.
|
|
164
|
+
// Defaults to false so existing deployments are unaffected.
|
|
165
|
+
var moduleBuster = module.exports.omitCacheBusterOnModules ? '' : buster;
|
|
155
166
|
|
|
156
167
|
return bluebird.resolve(_.map(fileArray, function (file) {
|
|
157
168
|
if (tag === STYLE_TAG) {
|
|
158
169
|
return `<link rel="stylesheet" type="text/css" href="${file}${buster}">`;
|
|
159
|
-
} else if (tag ===
|
|
160
|
-
return `<script
|
|
161
|
-
} else if (tag ===
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return `<
|
|
165
|
-
} else {
|
|
166
|
-
return `<script type="text/javascript" src="${file}${buster}"></script>`;
|
|
170
|
+
} else if (tag === MODULE_SCRIPT_TAG) {
|
|
171
|
+
return `<script type="module" src="${file}${moduleBuster}"></script>`;
|
|
172
|
+
} else if (tag === MODULEPRELOAD_TAG) {
|
|
173
|
+
// <link rel="modulepreload"> tells the browser to fetch ESM scripts early,
|
|
174
|
+
// during HTML parsing, before reaching the <script> tags at </body>.
|
|
175
|
+
return `<link rel="modulepreload" href="${file}${moduleBuster}">`;
|
|
167
176
|
}
|
|
168
|
-
}).join('\n'));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Filter the components rendered in this request, removing Webpack-managed
|
|
173
|
-
* assets so that we can fall back on Browserify.
|
|
174
|
-
*
|
|
175
|
-
* @param {Object} state - Amphora render state.
|
|
176
|
-
* @returns {string[]} - A list of components not available through Webpack.
|
|
177
|
-
*/
|
|
178
|
-
function filterManifestComponents(state) {
|
|
179
|
-
const site = state.locals.site,
|
|
180
|
-
assetDir = site && site.assetDir || MEDIA_DIRECTORY,
|
|
181
|
-
manifestName = site && site.manifestName || 'assets-manifest.json',
|
|
182
|
-
manifestFile = path.resolve(path.join(assetDir, manifestName));
|
|
183
|
-
let manifest;
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
manifest = files.tryRequire(manifestFile);
|
|
187
|
-
} catch (err) {
|
|
188
|
-
return state._components;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
177
|
|
|
192
|
-
|
|
193
|
-
|
|
178
|
+
// Default: classic <script src=...> for SCRIPT_TAG and any other value.
|
|
179
|
+
return `<script type="text/javascript" src="${file}${buster}"></script>`;
|
|
180
|
+
}).join('\n'));
|
|
194
181
|
}
|
|
195
182
|
|
|
196
183
|
/**
|
|
@@ -202,7 +189,6 @@ function getMediaMap(state) {
|
|
|
202
189
|
return {
|
|
203
190
|
styles: module.exports.getStyleFiles(state),
|
|
204
191
|
scripts: module.exports.getScriptFiles(state),
|
|
205
|
-
manifestAssets: module.exports.getManifestAssets(state)
|
|
206
192
|
};
|
|
207
193
|
}
|
|
208
194
|
|
|
@@ -274,19 +260,13 @@ function getStyleFiles(state) {
|
|
|
274
260
|
}
|
|
275
261
|
}
|
|
276
262
|
|
|
277
|
-
// check for clay linked font files
|
|
263
|
+
// check for clay compile linked? clay compile font files?
|
|
278
264
|
const defaultFontPath = path.join(assetDir, 'css', '_linked-fonts._default.css');
|
|
279
265
|
const siteFontPath = path.join(assetDir, 'css', `_linked-fonts.${siteStyleguide}.css`);
|
|
280
266
|
|
|
281
|
-
// check for inlined font files
|
|
282
|
-
const defaultInlinedFontPath = path.join(assetDir, 'css', '_inlined-fonts._default.css');
|
|
283
|
-
const siteInlinedFontPath = path.join(assetDir, 'css', `_inlined-fonts.${siteStyleguide}.css`);
|
|
284
|
-
|
|
285
267
|
// add any default and site font css
|
|
286
268
|
cssFilePaths.push(defaultFontPath);
|
|
287
269
|
cssFilePaths.push(siteFontPath);
|
|
288
|
-
cssFilePaths.push(defaultInlinedFontPath);
|
|
289
|
-
cssFilePaths.push(siteInlinedFontPath);
|
|
290
270
|
|
|
291
271
|
return cssFilePaths
|
|
292
272
|
.filter(files.fileExists)
|
|
@@ -309,7 +289,7 @@ function getScriptFiles(state) {
|
|
|
309
289
|
assetPath = site && site.assetPath || '',
|
|
310
290
|
assetHost = site && site.assetHost || '';
|
|
311
291
|
|
|
312
|
-
return
|
|
292
|
+
return state._components
|
|
313
293
|
.reduce((prev, name) => {
|
|
314
294
|
prev.push(
|
|
315
295
|
path.join(assetDir, 'js', `${name}.js`),
|
|
@@ -322,36 +302,6 @@ function getScriptFiles(state) {
|
|
|
322
302
|
.map(pathJoin(assetHost, assetPath, assetDir));
|
|
323
303
|
}
|
|
324
304
|
|
|
325
|
-
/**
|
|
326
|
-
* Read the asset manifest generated by the `clay pack` bundling command and
|
|
327
|
-
* check for scripts which match the rendered component names. The manifest for
|
|
328
|
-
* each asset lists its complete set of dependencies, so we dedupe them.
|
|
329
|
-
* Webpack's runtime is added to the beginning of the list, downstream legacy
|
|
330
|
-
* globals and Clay CLI's init script to the end.
|
|
331
|
-
*
|
|
332
|
-
* @param {Object} state - Amphora's render state.
|
|
333
|
-
* @return {string[]} A list of component assets.
|
|
334
|
-
*/
|
|
335
|
-
function getManifestAssets(state) {
|
|
336
|
-
const site = state.locals.site,
|
|
337
|
-
assetDir = site && site.assetDir || MEDIA_DIRECTORY,
|
|
338
|
-
assetHost = site && site.assetHost || '/',
|
|
339
|
-
manifestName = site && site.manifestName || 'assets-manifest.json',
|
|
340
|
-
manifestFile = path.resolve(path.join(assetDir, manifestName));
|
|
341
|
-
let manifest;
|
|
342
|
-
|
|
343
|
-
try {
|
|
344
|
-
manifest = files.tryRequire(manifestFile);
|
|
345
|
-
} catch (err) {
|
|
346
|
-
return [];
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
const entrypoints = _.get(manifest, 'entrypoints', []);
|
|
350
|
-
const scriptFiles = _.flatMap(entrypoints, entrypoint => _.get(entrypoint, 'assets.js', []));
|
|
351
|
-
|
|
352
|
-
return scriptFiles.map(script => url.resolve(assetHost, script));
|
|
353
|
-
}
|
|
354
|
-
|
|
355
305
|
/**
|
|
356
306
|
* Trim the path on the file system bythe link of the
|
|
357
307
|
* asset directory and then join it with either the assetHost
|
|
@@ -384,6 +334,14 @@ function configure(options, cacheBuster = '') {
|
|
|
384
334
|
if (options && _.isObject(options)) {
|
|
385
335
|
module.exports.editStylesTags = options.styles || false;
|
|
386
336
|
module.exports.editScriptsTags = options.scripts || false;
|
|
337
|
+
// modulepreload: when true, <link rel="modulepreload"> hints are injected
|
|
338
|
+
// into <head> for ESM scripts, and ?version= is omitted from module URLs
|
|
339
|
+
// since content-hashed filenames already provide cache busting.
|
|
340
|
+
// Opt-in only — defaults to false for backwards compatibility.
|
|
341
|
+
if (options.modulepreload !== undefined) {
|
|
342
|
+
module.exports.modulepreload = !!options.modulepreload;
|
|
343
|
+
module.exports.omitCacheBusterOnModules = !!options.modulepreload;
|
|
344
|
+
}
|
|
387
345
|
} else {
|
|
388
346
|
module.exports.editStylesTags = options;
|
|
389
347
|
module.exports.editScriptsTags = options;
|
|
@@ -403,6 +361,7 @@ function configure(options, cacheBuster = '') {
|
|
|
403
361
|
* @param {Object} state
|
|
404
362
|
* @return {Function}
|
|
405
363
|
*/
|
|
364
|
+
/* eslint-disable complexity */
|
|
406
365
|
function injectScriptsAndStyles(state) {
|
|
407
366
|
const { locals } = state;
|
|
408
367
|
|
|
@@ -418,26 +377,50 @@ function injectScriptsAndStyles(state) {
|
|
|
418
377
|
mediaMap = module.exports.getMediaMap(state);
|
|
419
378
|
|
|
420
379
|
// allow site to change the media map before applying it
|
|
380
|
+
// Expose rendered component names so resolveMedia can do per-component script resolution
|
|
381
|
+
// (e.g. pack-next manifest lookup) without needing a reference to the full state object.
|
|
382
|
+
locals._components = state._components;
|
|
421
383
|
if (setup.resolveMedia) mediaMap = setup.resolveMedia(mediaMap, locals) || mediaMap;
|
|
422
384
|
|
|
385
|
+
// moduleScripts: ESM scripts (e.g. from esbuild pack-next) that need type="module"
|
|
386
|
+
const moduleScriptFiles = mediaMap.moduleScripts || [];
|
|
387
|
+
|
|
388
|
+
mediaMap.moduleScripts = moduleScriptFiles.length
|
|
389
|
+
? injectTags(moduleScriptFiles, MODULE_SCRIPT_TAG)
|
|
390
|
+
: bluebird.resolve(false);
|
|
391
|
+
|
|
392
|
+
// modulePreloads: <link rel="modulepreload"> hints for <head>.
|
|
393
|
+
// Only active when configure({ modulepreload: true }) has been called — opt-in so
|
|
394
|
+
// sites not using the clay build pipeline are completely unaffected.
|
|
395
|
+
const modulePreloadFiles = module.exports.modulepreload
|
|
396
|
+
? mediaMap.modulePreloads || []
|
|
397
|
+
: [];
|
|
398
|
+
|
|
399
|
+
mediaMap.modulePreloads = modulePreloadFiles.length
|
|
400
|
+
? injectTags(modulePreloadFiles, MODULEPRELOAD_TAG)
|
|
401
|
+
: bluebird.resolve(false);
|
|
402
|
+
|
|
423
403
|
if (!locals.edit) {
|
|
424
404
|
mediaMap.styles = combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
|
|
425
|
-
mediaMap.scripts =
|
|
426
|
-
? injectTags(mediaMap.manifestAssets, locals.site, SCRIPT_TAG)
|
|
427
|
-
: combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
|
|
405
|
+
mediaMap.scripts = combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
|
|
428
406
|
} else {
|
|
429
|
-
mediaMap.styles = module.exports.editStylesTags ? injectTags(mediaMap.styles,
|
|
430
|
-
mediaMap.scripts = module.exports.editScriptsTags ? injectTags(mediaMap.scripts,
|
|
407
|
+
mediaMap.styles = module.exports.editStylesTags ? injectTags(mediaMap.styles, STYLE_TAG) : combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
|
|
408
|
+
mediaMap.scripts = module.exports.editScriptsTags ? injectTags(mediaMap.scripts, SCRIPT_TAG) : combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
|
|
431
409
|
}
|
|
432
410
|
|
|
433
411
|
return bluebird.props(mediaMap)
|
|
434
412
|
.then(combinedFiles => {
|
|
413
|
+
// modulepreload hints go first in <head>, before CSS, so the browser can
|
|
414
|
+
// start fetching ESM scripts at the earliest possible moment.
|
|
415
|
+
html = combinedFiles.modulePreloads ? appendMediaToTop(combinedFiles.modulePreloads, html) : html;
|
|
435
416
|
html = combinedFiles.styles ? appendMediaToTop(combinedFiles.styles, html) : html; // If there are styles, append them
|
|
417
|
+
html = combinedFiles.moduleScripts ? appendMediaToBottom(combinedFiles.moduleScripts, html) : html; // ESM module scripts (type="module")
|
|
436
418
|
html = combinedFiles.scripts ? appendMediaToBottom(combinedFiles.scripts, html) : html; // If there are scripts, append them
|
|
437
419
|
return html; // Return the compiled HTML
|
|
438
420
|
});
|
|
439
421
|
};
|
|
440
422
|
}
|
|
423
|
+
/* eslint-enable complexity */
|
|
441
424
|
|
|
442
425
|
module.exports.injectScriptsAndStyles = injectScriptsAndStyles;
|
|
443
426
|
module.exports.getMediaMap = getMediaMap;
|
|
@@ -445,8 +428,11 @@ module.exports.cacheBuster = '';
|
|
|
445
428
|
module.exports.configure = configure;
|
|
446
429
|
module.exports.editStylesTags = false;
|
|
447
430
|
module.exports.editScriptsTags = false;
|
|
431
|
+
// Opt-in flags for the clay build (esbuild) pipeline.
|
|
432
|
+
// Enable via configure({ modulepreload: true }).
|
|
433
|
+
module.exports.modulepreload = false;
|
|
434
|
+
module.exports.omitCacheBusterOnModules = false;
|
|
448
435
|
|
|
449
436
|
// For testing
|
|
450
|
-
module.exports.getManifestAssets = getManifestAssets;
|
|
451
437
|
module.exports.getScriptFiles = getScriptFiles;
|
|
452
438
|
module.exports.getStyleFiles = getStyleFiles;
|
package/lib/media.test.js
CHANGED
|
@@ -101,7 +101,7 @@ describe(_.startCase(filename), () => {
|
|
|
101
101
|
const fn = lib['getMediaMap'];
|
|
102
102
|
|
|
103
103
|
test('accepts state with empty components', () => {
|
|
104
|
-
expect(fn(state)).toEqual({
|
|
104
|
+
expect(fn(state)).toEqual({scripts: [], styles: []});
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
test('accepts list, empty slug (non-existent components)', () => {
|
|
@@ -114,7 +114,7 @@ describe(_.startCase(filename), () => {
|
|
|
114
114
|
_.omit(state, ['locals.site.slug'])
|
|
115
115
|
)
|
|
116
116
|
)
|
|
117
|
-
).toEqual({
|
|
117
|
+
).toEqual({scripts: [], styles: []});
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
test('accepts list and slug (non-existent components)', () => {
|
|
@@ -127,7 +127,7 @@ describe(_.startCase(filename), () => {
|
|
|
127
127
|
state
|
|
128
128
|
)
|
|
129
129
|
)
|
|
130
|
-
).toEqual({
|
|
130
|
+
).toEqual({scripts: [], styles: []});
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
test(
|
|
@@ -151,7 +151,7 @@ describe(_.startCase(filename), () => {
|
|
|
151
151
|
}
|
|
152
152
|
)
|
|
153
153
|
)
|
|
154
|
-
).toEqual({
|
|
154
|
+
).toEqual({scripts: expectedScriptFiles, styles: []});
|
|
155
155
|
}
|
|
156
156
|
);
|
|
157
157
|
});
|
|
@@ -625,117 +625,6 @@ 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
|
-
|
|
739
628
|
describe('injectScriptsAndStyles', () => {
|
|
740
629
|
const fn = lib['injectScriptsAndStyles'];
|
|
741
630
|
|
package/lib/render.js
CHANGED
|
@@ -38,9 +38,12 @@ function applyRenderHooks(ref, data, locals) {
|
|
|
38
38
|
*
|
|
39
39
|
* @param {String} ref
|
|
40
40
|
* @param {Object} locals
|
|
41
|
+
* @param {Object} res
|
|
42
|
+
* @param {String} self Clay ref of the component being rendered, e.g.
|
|
43
|
+
* "site.com/_components/article/instances/foo"
|
|
41
44
|
* @returns {Function}
|
|
42
45
|
*/
|
|
43
|
-
function applyPostRenderHooks(ref, locals) {
|
|
46
|
+
function applyPostRenderHooks(ref, locals, res, self) {
|
|
44
47
|
return (html) => {
|
|
45
48
|
|
|
46
49
|
// skip postRender hooks in edit mode
|
|
@@ -50,7 +53,7 @@ function applyPostRenderHooks(ref, locals) {
|
|
|
50
53
|
|
|
51
54
|
return setup.plugins.filter((plugin) => plugin.postRender)
|
|
52
55
|
.reduce((val, plugin) => {
|
|
53
|
-
return plugin.postRender(ref, html, locals);
|
|
56
|
+
return plugin.postRender(ref, html, locals, res, self);
|
|
54
57
|
}, html);
|
|
55
58
|
};
|
|
56
59
|
}
|
|
@@ -148,7 +151,7 @@ function render(data, meta, res) {
|
|
|
148
151
|
return applyRenderHooks(state._layoutRef || state.self, data, state.locals)
|
|
149
152
|
.then(makeHtml(state))
|
|
150
153
|
.then(mediaService.injectScriptsAndStyles(state))
|
|
151
|
-
.then(applyPostRenderHooks(state._layoutRef || state.self, state.locals))
|
|
154
|
+
.then(applyPostRenderHooks(state._layoutRef || state.self, state.locals, res, meta._ref))
|
|
152
155
|
.then(result => {
|
|
153
156
|
res.type('text/html');
|
|
154
157
|
res.send(result);
|
|
@@ -182,8 +185,12 @@ function logTime(hrStart, msg, route) {
|
|
|
182
185
|
};
|
|
183
186
|
}
|
|
184
187
|
|
|
185
|
-
function configure({ editAssetTags, cacheBuster }) {
|
|
186
|
-
|
|
188
|
+
function configure({ editAssetTags, cacheBuster, modulepreload }) {
|
|
189
|
+
const mediaOptions = editAssetTags && typeof editAssetTags === 'object'
|
|
190
|
+
? Object.assign({}, editAssetTags, modulepreload !== undefined ? { modulepreload } : {})
|
|
191
|
+
: editAssetTags;
|
|
192
|
+
|
|
193
|
+
mediaService.configure(mediaOptions, cacheBuster);
|
|
187
194
|
}
|
|
188
195
|
|
|
189
196
|
/**
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amphora-html",
|
|
3
|
-
"version": "6.0.0
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "An HTML renderer for component data",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.14.0"
|
|
8
|
+
},
|
|
6
9
|
"scripts": {
|
|
7
10
|
"test": "npm run eslint && npm run jest -- --coverage --no-cache",
|
|
8
11
|
"eslint": "eslint --max-warnings 0 lib test",
|
package/.circleci/config.yml
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
|
|
3
|
-
# Set defaults to reuse
|
|
4
|
-
defaults: &defaults
|
|
5
|
-
working_directory: ~/repo
|
|
6
|
-
docker:
|
|
7
|
-
- image: circleci/node:8.10.0
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
<<: *defaults
|
|
12
|
-
steps:
|
|
13
|
-
- checkout
|
|
14
|
-
|
|
15
|
-
- restore_cache:
|
|
16
|
-
keys:
|
|
17
|
-
- v2-dependencies-{{ checksum "package.json" }}
|
|
18
|
-
# fallback to using the latest cache if no exact match is found
|
|
19
|
-
- v2-dependencies-
|
|
20
|
-
|
|
21
|
-
- run: npm install
|
|
22
|
-
- run:
|
|
23
|
-
name: Run tests
|
|
24
|
-
command: npm test
|
|
25
|
-
- run:
|
|
26
|
-
name: Send to Coveralls
|
|
27
|
-
command: cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
|
28
|
-
- save_cache:
|
|
29
|
-
paths:
|
|
30
|
-
- node_modules
|
|
31
|
-
key: v2-dependencies-{{ checksum "package.json" }}
|
|
32
|
-
|
|
33
|
-
- persist_to_workspace:
|
|
34
|
-
root: ~/repo
|
|
35
|
-
paths: .
|
|
36
|
-
|
|
37
|
-
workflows:
|
|
38
|
-
version: 2
|
|
39
|
-
test-deploy:
|
|
40
|
-
jobs:
|
|
41
|
-
- test:
|
|
42
|
-
filters:
|
|
43
|
-
tags:
|
|
44
|
-
only: /^v[0-9]+\.[0-9]+\.[0-9]+/
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
on: push
|
|
2
|
-
name: Deploy to GitHub Pages
|
|
3
|
-
jobs:
|
|
4
|
-
filterBranch:
|
|
5
|
-
name: Filter branch
|
|
6
|
-
runs-on: ubuntu-latest
|
|
7
|
-
steps:
|
|
8
|
-
- uses: actions/checkout@master
|
|
9
|
-
- name: Filter branch
|
|
10
|
-
uses: actions/bin/filter@master
|
|
11
|
-
with:
|
|
12
|
-
args: branch master
|
|
13
|
-
- name: Install
|
|
14
|
-
uses: actions/npm@master
|
|
15
|
-
with:
|
|
16
|
-
args: install --prefix ./website
|
|
17
|
-
- name: Update version
|
|
18
|
-
uses: clay/docusaurus-github-action@master
|
|
19
|
-
with:
|
|
20
|
-
args: version
|
|
21
|
-
- name: Build and push docs
|
|
22
|
-
uses: clay/docusaurus-github-action@master
|
|
23
|
-
env:
|
|
24
|
-
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
25
|
-
with:
|
|
26
|
-
args: deploy
|