@adobe/helix-html-pipeline 5.0.1 → 5.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +4 -4
- package/src/steps/extract-metadata.js +69 -9
- package/src/steps/render.js +1 -46
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [5.0.3](https://github.com/adobe/helix-html-pipeline/compare/v5.0.2...v5.0.3) (2023-09-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* properly rewrite meta image ([#406](https://github.com/adobe/helix-html-pipeline/issues/406)) ([d0c173f](https://github.com/adobe/helix-html-pipeline/commit/d0c173f21942f6fb123ff6d4288364d4b9f0ec98)), closes [#405](https://github.com/adobe/helix-html-pipeline/issues/405)
|
|
7
|
+
|
|
8
|
+
## [5.0.2](https://github.com/adobe/helix-html-pipeline/compare/v5.0.1...v5.0.2) (2023-09-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* supress empty non-fallback values ([#399](https://github.com/adobe/helix-html-pipeline/issues/399)) ([1e5629d](https://github.com/adobe/helix-html-pipeline/commit/1e5629d7cb08de210c713654479bd6d5301a905e))
|
|
14
|
+
|
|
1
15
|
## [5.0.1](https://github.com/adobe/helix-html-pipeline/compare/v5.0.0...v5.0.1) (2023-09-09)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-html-pipeline",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "Helix HTML Pipeline",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"@markedjs/html-differ": "4.0.2",
|
|
75
75
|
"@semantic-release/changelog": "6.0.3",
|
|
76
76
|
"@semantic-release/git": "10.0.1",
|
|
77
|
-
"@semantic-release/npm": "10.0.
|
|
77
|
+
"@semantic-release/npm": "10.0.6",
|
|
78
78
|
"c8": "8.0.1",
|
|
79
79
|
"eslint": "8.49.0",
|
|
80
80
|
"eslint-import-resolver-exports": "1.0.0-beta.5",
|
|
81
81
|
"eslint-plugin-header": "3.1.1",
|
|
82
82
|
"eslint-plugin-import": "2.28.1",
|
|
83
|
-
"esmock": "2.
|
|
83
|
+
"esmock": "2.5.1",
|
|
84
84
|
"husky": "8.0.3",
|
|
85
85
|
"js-yaml": "4.1.0",
|
|
86
86
|
"jsdom": "22.1.0",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"mocha": "10.2.0",
|
|
90
90
|
"mocha-multi-reporters": "1.5.1",
|
|
91
91
|
"mocha-suppress-logs": "0.3.1",
|
|
92
|
-
"semantic-release": "21.1.
|
|
92
|
+
"semantic-release": "21.1.2"
|
|
93
93
|
},
|
|
94
94
|
"lint-staged": {
|
|
95
95
|
"*.js": "eslint",
|
|
@@ -142,12 +142,25 @@ function extractDescription(hast) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
* Extracts the metadata and stores it in the content
|
|
145
|
+
* Extracts the metadata from config and the metadata block and stores it in the content.meta.page:
|
|
146
|
+
* - all the non-empty values from the config metadata are applied.
|
|
147
|
+
* - config value with an empty string (explicit "") are removed from the result
|
|
148
|
+
* - all the values from the metadata block are applied. empty values remain empty for the
|
|
149
|
+
* properties that can have a default: 'title', 'description', 'image', 'image-alt', 'url'
|
|
150
|
+
* the others are removed.
|
|
151
|
+
* - the defaults for 'title', 'description', 'image', 'image-alt', 'url' are applied if missing
|
|
152
|
+
* - twitter: properties default to their og: counterparts if missing.
|
|
153
|
+
*
|
|
146
154
|
* @type PipelineStep
|
|
147
155
|
* @param {PipelineState} state
|
|
148
156
|
* @param {PipelineRequest} req
|
|
149
157
|
*/
|
|
150
158
|
export default function extractMetaData(state, req) {
|
|
159
|
+
const FIXED = new Set([
|
|
160
|
+
'title', 'description', 'image', 'image-alt', 'url',
|
|
161
|
+
'twitter:card', 'og:url', 'canonical',
|
|
162
|
+
]);
|
|
163
|
+
|
|
151
164
|
const { content } = state;
|
|
152
165
|
const { meta, hast } = content;
|
|
153
166
|
|
|
@@ -168,7 +181,11 @@ export default function extractMetaData(state, req) {
|
|
|
168
181
|
});
|
|
169
182
|
|
|
170
183
|
// apply document local overrides
|
|
171
|
-
Object.
|
|
184
|
+
Object.entries(getLocalMetadata(hast)).forEach(([name, value]) => {
|
|
185
|
+
if (value || FIXED.has(name)) {
|
|
186
|
+
metaConfig[name] = value;
|
|
187
|
+
}
|
|
188
|
+
});
|
|
172
189
|
|
|
173
190
|
// first process supported metadata properties
|
|
174
191
|
[
|
|
@@ -193,9 +210,6 @@ export default function extractMetaData(state, req) {
|
|
|
193
210
|
meta['twitter:card'] = 'summary_large_image';
|
|
194
211
|
}
|
|
195
212
|
|
|
196
|
-
// add rest to meta.custom
|
|
197
|
-
meta.custom = metaConfig;
|
|
198
|
-
|
|
199
213
|
if (meta.keywords) {
|
|
200
214
|
meta.keywords = toList(meta.keywords).join(', ');
|
|
201
215
|
}
|
|
@@ -234,11 +248,57 @@ export default function extractMetaData(state, req) {
|
|
|
234
248
|
}
|
|
235
249
|
|
|
236
250
|
if (!('image' in meta)) {
|
|
237
|
-
meta.image =
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
251
|
+
meta.image = content.image || '/default-meta-image.png';
|
|
252
|
+
}
|
|
253
|
+
if (meta.image) {
|
|
254
|
+
meta.image = getAbsoluteUrl(state, optimizeMetaImage(state.info.path, meta.image));
|
|
241
255
|
}
|
|
242
256
|
|
|
243
257
|
meta.imageAlt = meta['image-alt'] ?? content.imageAlt;
|
|
258
|
+
|
|
259
|
+
// compute the final page metadata
|
|
260
|
+
const metadata = {
|
|
261
|
+
description: meta.description,
|
|
262
|
+
keywords: meta.keywords,
|
|
263
|
+
'og:title': meta.title,
|
|
264
|
+
'og:description': meta.description,
|
|
265
|
+
'og:url': meta.url,
|
|
266
|
+
'og:image': meta.image,
|
|
267
|
+
'og:image:secure_url': meta.image,
|
|
268
|
+
'og:image:alt': meta.imageAlt,
|
|
269
|
+
'og:updated_time': meta.modified_time,
|
|
270
|
+
'article:tag': meta.tags || [],
|
|
271
|
+
'article:section': meta.section,
|
|
272
|
+
'article:published_time': meta.published_time,
|
|
273
|
+
'article:modified_time': meta.modified_time,
|
|
274
|
+
'twitter:card': meta['twitter:card'],
|
|
275
|
+
'twitter:title': '',
|
|
276
|
+
'twitter:description': '',
|
|
277
|
+
'twitter:image': '',
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// append custom metadata
|
|
281
|
+
Object.assign(metadata, metaConfig);
|
|
282
|
+
|
|
283
|
+
// fallback for twitter
|
|
284
|
+
const FALLBACKS = [
|
|
285
|
+
['twitter:title', 'og:title'],
|
|
286
|
+
['twitter:description', 'og:description'],
|
|
287
|
+
['twitter:image', 'og:image'],
|
|
288
|
+
];
|
|
289
|
+
|
|
290
|
+
for (const [from, to] of FALLBACKS) {
|
|
291
|
+
if (!(from in metaConfig)) {
|
|
292
|
+
metadata[from] = metadata[to];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// remove undefined metadata
|
|
297
|
+
for (const name of Object.keys(metadata)) {
|
|
298
|
+
if (metadata[name] === undefined) {
|
|
299
|
+
delete metadata[name];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
meta.page = metadata;
|
|
244
304
|
}
|
package/src/steps/render.js
CHANGED
|
@@ -55,54 +55,9 @@ export default async function render(state, req, res) {
|
|
|
55
55
|
$head.children.push(h('title', meta.title));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
// add meta
|
|
59
|
-
// (this is so complicated to keep the order backward compatible to make the diff tests happy)
|
|
60
|
-
const metadata = {
|
|
61
|
-
'og:title': meta.title,
|
|
62
|
-
'og:description': meta.description,
|
|
63
|
-
'og:url': meta.url,
|
|
64
|
-
'og:image': meta.image,
|
|
65
|
-
'og:image:secure_url': meta.image,
|
|
66
|
-
'og:image:alt': meta.imageAlt,
|
|
67
|
-
'og:updated_time': meta.modified_time,
|
|
68
|
-
'article:tag': meta.tags || [],
|
|
69
|
-
'article:section': meta.section,
|
|
70
|
-
'article:published_time': meta.published_time,
|
|
71
|
-
'article:modified_time': meta.modified_time,
|
|
72
|
-
'twitter:card': meta['twitter:card'],
|
|
73
|
-
'twitter:title': '',
|
|
74
|
-
'twitter:description': '',
|
|
75
|
-
'twitter:image': '',
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// append custom metadata
|
|
79
|
-
Object.assign(metadata, meta.custom);
|
|
80
|
-
|
|
81
|
-
// fallback for twitter
|
|
82
|
-
const FALLBACKS = [
|
|
83
|
-
['twitter:title', 'og:title'],
|
|
84
|
-
['twitter:description', 'og:description'],
|
|
85
|
-
['twitter:image', 'og:image'],
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
for (const [from, to] of FALLBACKS) {
|
|
89
|
-
if (!(from in meta.custom)) {
|
|
90
|
-
metadata[from] = metadata[to];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// remove undefined metadata
|
|
95
|
-
for (const name of Object.keys(metadata)) {
|
|
96
|
-
if (metadata[name] === undefined) {
|
|
97
|
-
delete metadata[name];
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
58
|
appendElement($head, createElement('link', 'rel', 'canonical', 'href', meta.canonical));
|
|
102
|
-
appendElement($head, createElement('meta', 'name', 'description', 'content', meta.description));
|
|
103
|
-
appendElement($head, createElement('meta', 'name', 'keywords', 'content', meta.keywords));
|
|
104
59
|
|
|
105
|
-
for (const [name, value] of Object.entries(
|
|
60
|
+
for (const [name, value] of Object.entries(meta.page)) {
|
|
106
61
|
const attr = name.includes(':') && !name.startsWith('twitter:') ? 'property' : 'name';
|
|
107
62
|
if (Array.isArray(value)) {
|
|
108
63
|
for (const v of value) {
|