@adobe/helix-html-pipeline 3.9.0 → 3.10.1
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 +12 -12
- package/src/forms-pipe.js +31 -19
- package/src/html-pipe.js +5 -6
- package/src/json-pipe.js +8 -0
- package/src/steps/create-pictures.js +1 -1
- package/src/steps/fetch-config.js +15 -0
- package/src/steps/render-code.js +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [3.10.1](https://github.com/adobe/helix-html-pipeline/compare/v3.10.0...v3.10.1) (2023-04-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* read contentbus-id from helix-config ([#291](https://github.com/adobe/helix-html-pipeline/issues/291)) ([c3ff2a8](https://github.com/adobe/helix-html-pipeline/commit/c3ff2a85a33f34c81a8d99f9afcbe085691734e9))
|
|
7
|
+
|
|
8
|
+
# [3.10.0](https://github.com/adobe/helix-html-pipeline/compare/v3.9.0...v3.10.0) (2023-03-28)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **picture:** update mobile breakpoint to 600px ([#280](https://github.com/adobe/helix-html-pipeline/issues/280)) ([6c72cba](https://github.com/adobe/helix-html-pipeline/commit/6c72cbaead55fb69b1c7d4c102052cc09a330b50))
|
|
14
|
+
|
|
1
15
|
# [3.9.0](https://github.com/adobe/helix-html-pipeline/compare/v3.8.12...v3.9.0) (2023-03-23)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-html-pipeline",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.1",
|
|
4
4
|
"description": "Helix HTML Pipeline",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"mdast-util-gfm-table": "1.0.7",
|
|
57
57
|
"mdast-util-gfm-task-list-item": "1.0.2",
|
|
58
58
|
"mdast-util-to-hast": "12.3.0",
|
|
59
|
-
"mdast-util-to-string": "3.
|
|
60
|
-
"micromark-extension-gfm-footnote": "1.0
|
|
61
|
-
"micromark-extension-gfm-strikethrough": "1.0.
|
|
59
|
+
"mdast-util-to-string": "3.2.0",
|
|
60
|
+
"micromark-extension-gfm-footnote": "1.1.0",
|
|
61
|
+
"micromark-extension-gfm-strikethrough": "1.0.5",
|
|
62
62
|
"micromark-extension-gfm-table": "1.0.5",
|
|
63
|
-
"micromark-extension-gfm-tagfilter": "1.0.
|
|
64
|
-
"micromark-extension-gfm-task-list-item": "1.0.
|
|
63
|
+
"micromark-extension-gfm-tagfilter": "1.0.2",
|
|
64
|
+
"micromark-extension-gfm-task-list-item": "1.0.4",
|
|
65
65
|
"micromark-util-combine-extensions": "1.0.0",
|
|
66
66
|
"mime": "3.0.0",
|
|
67
67
|
"rehype-format": "4.0.1",
|
|
@@ -79,24 +79,24 @@
|
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@adobe/eslint-config-helix": "2.0.2",
|
|
81
81
|
"@markedjs/html-differ": "4.0.2",
|
|
82
|
-
"@semantic-release/changelog": "6.0.
|
|
82
|
+
"@semantic-release/changelog": "6.0.3",
|
|
83
83
|
"@semantic-release/git": "10.0.1",
|
|
84
|
-
"@semantic-release/npm": "
|
|
84
|
+
"@semantic-release/npm": "10.0.3",
|
|
85
85
|
"c8": "7.13.0",
|
|
86
|
-
"eslint": "8.
|
|
86
|
+
"eslint": "8.38.0",
|
|
87
87
|
"eslint-import-resolver-exports": "1.0.0-beta.5",
|
|
88
88
|
"eslint-plugin-header": "3.1.1",
|
|
89
89
|
"eslint-plugin-import": "2.27.5",
|
|
90
|
-
"esmock": "2.1
|
|
90
|
+
"esmock": "2.2.1",
|
|
91
91
|
"husky": "8.0.3",
|
|
92
92
|
"js-yaml": "4.1.0",
|
|
93
93
|
"jsdom": "21.1.1",
|
|
94
94
|
"junit-report-builder": "3.0.1",
|
|
95
|
-
"lint-staged": "13.2.
|
|
95
|
+
"lint-staged": "13.2.1",
|
|
96
96
|
"mocha": "10.2.0",
|
|
97
97
|
"mocha-multi-reporters": "1.5.1",
|
|
98
98
|
"remark-gfm": "3.0.1",
|
|
99
|
-
"semantic-release": "
|
|
99
|
+
"semantic-release": "21.0.1"
|
|
100
100
|
},
|
|
101
101
|
"lint-staged": {
|
|
102
102
|
"*.js": "eslint",
|
package/src/forms-pipe.js
CHANGED
|
@@ -14,6 +14,7 @@ import { PipelineResponse } from './PipelineResponse.js';
|
|
|
14
14
|
import fetchConfigAll from './steps/fetch-config-all.js';
|
|
15
15
|
import setCustomResponseHeaders from './steps/set-custom-response-headers.js';
|
|
16
16
|
import { authenticate } from './steps/authenticate.js';
|
|
17
|
+
import fetchConfig from './steps/fetch-config.js';
|
|
17
18
|
|
|
18
19
|
function error(log, msg, status, response) {
|
|
19
20
|
log.error(msg);
|
|
@@ -83,25 +84,36 @@ export async function extractBodyData(request) {
|
|
|
83
84
|
* Handle a pipeline POST request.
|
|
84
85
|
* At this point POST's only apply to json files that are backed by a workbook.
|
|
85
86
|
* @param {PipelineState} state pipeline options
|
|
86
|
-
* @param {PipelineRequest}
|
|
87
|
+
* @param {PipelineRequest} req
|
|
87
88
|
* @returns {Promise<PipelineResponse>} a response
|
|
88
89
|
*/
|
|
89
|
-
export async function formsPipe(state,
|
|
90
|
+
export async function formsPipe(state, req) {
|
|
90
91
|
const { log } = state;
|
|
91
92
|
state.type = 'form';
|
|
92
93
|
|
|
93
94
|
// todo: improve
|
|
94
|
-
const
|
|
95
|
+
const res = new PipelineResponse('', {
|
|
95
96
|
headers: {
|
|
96
97
|
'content-type': 'text/plain; charset=utf-8',
|
|
97
98
|
},
|
|
98
99
|
});
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
try {
|
|
101
|
+
await fetchConfig(state, req, res);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
// ignore
|
|
104
|
+
}
|
|
105
|
+
if (!state.contentBusId) {
|
|
106
|
+
res.status = 400;
|
|
107
|
+
res.headers.set('x-error', 'contentBusId missing');
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await fetchConfigAll(state, req, res);
|
|
112
|
+
await authenticate(state, req, res);
|
|
113
|
+
if (res.error) {
|
|
114
|
+
return res;
|
|
103
115
|
}
|
|
104
|
-
await setCustomResponseHeaders(state,
|
|
116
|
+
await setCustomResponseHeaders(state, req, res);
|
|
105
117
|
|
|
106
118
|
const {
|
|
107
119
|
owner, repo, ref, contentBusId, partition, s3Loader,
|
|
@@ -111,7 +123,7 @@ export async function formsPipe(state, request) {
|
|
|
111
123
|
|
|
112
124
|
// block all POSTs to resources with extensions
|
|
113
125
|
if (state.info.originalExtension !== '') {
|
|
114
|
-
return error(log, 'POST to URL with extension not allowed', 405,
|
|
126
|
+
return error(log, 'POST to URL with extension not allowed', 405, res);
|
|
115
127
|
}
|
|
116
128
|
|
|
117
129
|
// head workbook in content bus
|
|
@@ -122,22 +134,22 @@ export async function formsPipe(state, request) {
|
|
|
122
134
|
|
|
123
135
|
let body;
|
|
124
136
|
try {
|
|
125
|
-
body = await extractBodyData(
|
|
137
|
+
body = await extractBodyData(req);
|
|
126
138
|
} catch (err) {
|
|
127
|
-
return error(log, err.message, 400,
|
|
139
|
+
return error(log, err.message, 400, res);
|
|
128
140
|
}
|
|
129
141
|
|
|
130
142
|
const sheets = resourceFetchResponse.headers.get('x-amz-meta-x-sheet-names');
|
|
131
143
|
if (!sheets) {
|
|
132
|
-
return error(log, `Target workbook at ${resourcePath} missing x-sheet-names header.`, 403,
|
|
144
|
+
return error(log, `Target workbook at ${resourcePath} missing x-sheet-names header.`, 403, res);
|
|
133
145
|
}
|
|
134
146
|
|
|
135
147
|
const sourceLocation = resourceFetchResponse.headers.get('x-amz-meta-x-source-location');
|
|
136
|
-
const referer =
|
|
148
|
+
const referer = req.headers.get('referer') || 'unknown';
|
|
137
149
|
const sheetNames = sheets.split(',').map((s) => s.trim());
|
|
138
150
|
|
|
139
151
|
if (!sourceLocation || !sheetNames.includes('incoming')) {
|
|
140
|
-
return error(log, `Target workbook at ${resourcePath} is not setup to intake data.`, 403,
|
|
152
|
+
return error(log, `Target workbook at ${resourcePath} is not setup to intake data.`, 403, res);
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
// Send message to SQS if workbook contains and incoming
|
|
@@ -159,11 +171,11 @@ export async function formsPipe(state, request) {
|
|
|
159
171
|
try {
|
|
160
172
|
// Send message to forms queue
|
|
161
173
|
const { requestId, messageId } = await state.messageDispatcher.dispatch(message);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return
|
|
174
|
+
res.status = 201;
|
|
175
|
+
res.headers.set('x-request-id', requestId);
|
|
176
|
+
res.headers.set('x-message-id', messageId);
|
|
177
|
+
return res;
|
|
166
178
|
} catch (err) {
|
|
167
|
-
return error(log, `Failed to send message to forms queue: ${err}`, 500,
|
|
179
|
+
return error(log, `Failed to send message to forms queue: ${err}`, 500, res);
|
|
168
180
|
}
|
|
169
181
|
}
|
package/src/html-pipe.js
CHANGED
|
@@ -71,15 +71,14 @@ export async function htmlPipe(state, req) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
if (!state.contentBusId) {
|
|
75
|
-
res.status = 400;
|
|
76
|
-
res.headers.set('x-error', 'contentBusId missing');
|
|
77
|
-
return res;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
74
|
try { // fetch config first, since we need to compute the content-bus-id from the fstab ...
|
|
81
75
|
state.timer?.update('config-fetch');
|
|
82
76
|
await fetchConfig(state, req, res);
|
|
77
|
+
if (!state.contentBusId) {
|
|
78
|
+
res.status = 400;
|
|
79
|
+
res.headers.set('x-error', 'contentBusId missing');
|
|
80
|
+
return res;
|
|
81
|
+
}
|
|
83
82
|
|
|
84
83
|
// ...and apply the folder mapping
|
|
85
84
|
await folderMapping(state);
|
package/src/json-pipe.js
CHANGED
|
@@ -102,6 +102,14 @@ export async function jsonPipe(state, req) {
|
|
|
102
102
|
try {
|
|
103
103
|
// fetch config and apply the folder mapping
|
|
104
104
|
await fetchConfig(state, req);
|
|
105
|
+
if (!state.contentBusId) {
|
|
106
|
+
return new PipelineResponse('', {
|
|
107
|
+
status: 400,
|
|
108
|
+
headers: {
|
|
109
|
+
'x-error': 'contentBusId missing',
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
105
113
|
await folderMapping(state);
|
|
106
114
|
|
|
107
115
|
/** @type PipelineResponse */
|
|
@@ -47,6 +47,21 @@ export default async function fetchConfig(state, req, res) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// set contentbusid from header if missing in config
|
|
51
|
+
const cbid = ret.headers.get('x-contentbus-id');
|
|
52
|
+
if (!config.content && cbid) {
|
|
53
|
+
config.content = {
|
|
54
|
+
data: {
|
|
55
|
+
'/': {
|
|
56
|
+
contentBusId: cbid.substring(2),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (!state.contentBusId) {
|
|
62
|
+
state.contentBusId = config.content?.data?.['/']?.contentBusId;
|
|
63
|
+
}
|
|
64
|
+
|
|
50
65
|
if (res) {
|
|
51
66
|
// also update last-modified
|
|
52
67
|
const configLastModified = extractLastModified(ret.headers);
|
package/src/steps/render-code.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import mime from 'mime';
|
|
13
13
|
|
|
14
|
+
const CHARSET_RE = /charset=([^()<>@,;:"/[\]?.=\s]*)/i;
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* "Renders" the content from the code-bus as-is
|
|
16
18
|
* @type PipelineStep
|
|
@@ -21,5 +23,13 @@ import mime from 'mime';
|
|
|
21
23
|
*/
|
|
22
24
|
export default async function renderCode(state, req, res) {
|
|
23
25
|
res.body = state.content.data;
|
|
24
|
-
|
|
26
|
+
let contentType = mime.getType(state.info.resourcePath);
|
|
27
|
+
const originalType = res.headers.get('content-type');
|
|
28
|
+
if (originalType) {
|
|
29
|
+
const match = CHARSET_RE.exec(originalType);
|
|
30
|
+
if (match) {
|
|
31
|
+
contentType += `; charset=${match[1]}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
res.headers.set('content-type', contentType);
|
|
25
35
|
}
|