amphora-html 5.1.0 → 5.2.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/.github/workflows/push.yml +35 -22
- package/lib/media.js +66 -6
- package/lib/render.js +9 -2
- package/package.json +1 -1
- package/.circleci/config.yml +0 -44
|
@@ -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: [18, 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
|
+
|
|
@@ -1,26 +1,39 @@
|
|
|
1
|
-
on: push
|
|
2
1
|
name: Deploy to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
3
7
|
jobs:
|
|
4
|
-
|
|
5
|
-
name:
|
|
8
|
+
deploy-docs:
|
|
9
|
+
name: Deploy docs
|
|
6
10
|
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
7
13
|
steps:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
with:
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
|
|
18
|
+
- name: Use Node.js
|
|
19
|
+
uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: '16'
|
|
22
|
+
|
|
23
|
+
- name: Install website dependencies
|
|
24
|
+
run: npm install
|
|
25
|
+
working-directory: website
|
|
26
|
+
|
|
27
|
+
- name: Update Docusaurus version
|
|
28
|
+
run: npm run version
|
|
29
|
+
working-directory: website
|
|
30
|
+
|
|
31
|
+
- name: Build Docusaurus site
|
|
32
|
+
run: npm run build
|
|
33
|
+
working-directory: website
|
|
34
|
+
|
|
35
|
+
- name: Publish docs to gh-pages
|
|
36
|
+
uses: peaceiris/actions-gh-pages@v4
|
|
37
|
+
with:
|
|
38
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
publish_dir: ./website/build/amphora-html
|
package/lib/media.js
CHANGED
|
@@ -6,9 +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',
|
|
11
|
+
MODULE_SCRIPT_TAG = 'module',
|
|
12
|
+
MODULEPRELOAD_TAG = 'modulepreload',
|
|
12
13
|
MEDIA_DIRECTORY = path.join(process.cwd(), 'public');
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -147,15 +148,35 @@ function appendMediaToBottom(scripts, html) {
|
|
|
147
148
|
return splice(html, index, scripts);
|
|
148
149
|
}
|
|
149
150
|
|
|
150
|
-
|
|
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) {
|
|
151
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;
|
|
152
166
|
|
|
153
167
|
return bluebird.resolve(_.map(fileArray, function (file) {
|
|
154
168
|
if (tag === STYLE_TAG) {
|
|
155
169
|
return `<link rel="stylesheet" type="text/css" href="${file}${buster}">`;
|
|
156
|
-
} else {
|
|
157
|
-
return `<script type="
|
|
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}">`;
|
|
158
176
|
}
|
|
177
|
+
|
|
178
|
+
// Default: classic <script src=...> for SCRIPT_TAG and any other value.
|
|
179
|
+
return `<script type="text/javascript" src="${file}${buster}"></script>`;
|
|
159
180
|
}).join('\n'));
|
|
160
181
|
}
|
|
161
182
|
|
|
@@ -313,6 +334,14 @@ function configure(options, cacheBuster = '') {
|
|
|
313
334
|
if (options && _.isObject(options)) {
|
|
314
335
|
module.exports.editStylesTags = options.styles || false;
|
|
315
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
|
+
}
|
|
316
345
|
} else {
|
|
317
346
|
module.exports.editStylesTags = options;
|
|
318
347
|
module.exports.editScriptsTags = options;
|
|
@@ -332,6 +361,7 @@ function configure(options, cacheBuster = '') {
|
|
|
332
361
|
* @param {Object} state
|
|
333
362
|
* @return {Function}
|
|
334
363
|
*/
|
|
364
|
+
/* eslint-disable complexity */
|
|
335
365
|
function injectScriptsAndStyles(state) {
|
|
336
366
|
const { locals } = state;
|
|
337
367
|
|
|
@@ -347,24 +377,50 @@ function injectScriptsAndStyles(state) {
|
|
|
347
377
|
mediaMap = module.exports.getMediaMap(state);
|
|
348
378
|
|
|
349
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;
|
|
350
383
|
if (setup.resolveMedia) mediaMap = setup.resolveMedia(mediaMap, locals) || mediaMap;
|
|
351
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
|
+
|
|
352
403
|
if (!locals.edit) {
|
|
353
404
|
mediaMap.styles = combineFileContents(mediaMap.styles, 'public/css', '/css/', STYLE_TAG);
|
|
354
405
|
mediaMap.scripts = combineFileContents(mediaMap.scripts, 'public/js', '/js/', SCRIPT_TAG);
|
|
355
406
|
} else {
|
|
356
|
-
mediaMap.styles = module.exports.editStylesTags ? injectTags(mediaMap.styles,
|
|
357
|
-
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);
|
|
358
409
|
}
|
|
359
410
|
|
|
360
411
|
return bluebird.props(mediaMap)
|
|
361
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;
|
|
362
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")
|
|
363
418
|
html = combinedFiles.scripts ? appendMediaToBottom(combinedFiles.scripts, html) : html; // If there are scripts, append them
|
|
364
419
|
return html; // Return the compiled HTML
|
|
365
420
|
});
|
|
366
421
|
};
|
|
367
422
|
}
|
|
423
|
+
/* eslint-enable complexity */
|
|
368
424
|
|
|
369
425
|
module.exports.injectScriptsAndStyles = injectScriptsAndStyles;
|
|
370
426
|
module.exports.getMediaMap = getMediaMap;
|
|
@@ -372,6 +428,10 @@ module.exports.cacheBuster = '';
|
|
|
372
428
|
module.exports.configure = configure;
|
|
373
429
|
module.exports.editStylesTags = false;
|
|
374
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;
|
|
375
435
|
|
|
376
436
|
// For testing
|
|
377
437
|
module.exports.getScriptFiles = getScriptFiles;
|
package/lib/render.js
CHANGED
|
@@ -38,6 +38,9 @@ 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
46
|
function applyPostRenderHooks(ref, locals, res, self) {
|
|
@@ -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
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]+/
|