@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 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.1",
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.5",
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.4.1",
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.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 meta
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.assign(metaConfig, getLocalMetadata(hast));
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 = getAbsoluteUrl(
238
- state,
239
- optimizeMetaImage(state.info.path, meta.image || content.image || '/default-meta-image.png'),
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
  }
@@ -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(metadata)) {
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) {