@adobe/aem-cli 16.19.7 → 16.19.8
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 +7 -0
- package/README.md +7 -0
- package/package.json +1 -1
- package/src/server/HelixProject.js +6 -0
- package/src/server/HelixServer.js +39 -34
- package/src/up.cmd.js +7 -1
- package/src/up.js +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [16.19.8](https://github.com/adobe/helix-cli/compare/v16.19.7...v16.19.8) (2026-05-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Add --preferPlainHtml flag ([#2728](https://github.com/adobe/helix-cli/issues/2728)) ([0ae790f](https://github.com/adobe/helix-cli/commit/0ae790fdc9ac5a36385ef2efa9e9f717c3321eaa))
|
|
7
|
+
|
|
1
8
|
## [16.19.7](https://github.com/adobe/helix-cli/compare/v16.19.6...v16.19.7) (2026-05-19)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -99,6 +99,12 @@ Plain HTML files contain only the main content and an optional metadata block. T
|
|
|
99
99
|
- Merges in `head.html` content
|
|
100
100
|
- The metadata block is removed from the rendered content and converted to meta tags in the `<head>`.
|
|
101
101
|
|
|
102
|
+
When a request resolves to `<stem>`, the CLI looks up `<stem>.html` first and falls back to `<stem>.plain.html`. Pass `--preferPlainHtml` to reverse this order — useful when you keep both files side-by-side and want the plain version to win:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
$ aem up --html-folder drafts --preferPlainHtml
|
|
106
|
+
```
|
|
107
|
+
|
|
102
108
|
### setting up a self-signed cert for using https
|
|
103
109
|
|
|
104
110
|
1. create the certificate
|
|
@@ -188,6 +194,7 @@ If present, `ALL_PROXY` is used as fallback if there is no other match.
|
|
|
188
194
|
| `--forward-browser-logs` | `AEM_FORWARD_BROWSER_LOGS` | `false` | Forward browser console logs to terminal. |
|
|
189
195
|
| `--html-folder` | `AEM_HTML_FOLDER` | undefined | Serve HTML files from folder without extensions. |
|
|
190
196
|
| `--html-mount` | `AEM_HTML_MOUNT` | `/FOLDER` | URL path where html-folder files are served. |
|
|
197
|
+
| `--prefer-plain-html` | `AEM_PREFER_PLAIN_HTML` | `false` | Prefer `<stem>.plain.html` over `<stem>.html` when both exist. |
|
|
191
198
|
| `--open` | `AEM_OPEN` | `/` | Open a browser window at specified path after server start. |
|
|
192
199
|
| `--no-open` | `AEM_NO_OPEN` | `false` | Disable automatic opening of browser window. |
|
|
193
200
|
| `--tls-key` | `AEM_TLS_KEY` | undefined | Path to .key file (for enabling TLS) |
|
package/package.json
CHANGED
|
@@ -99,6 +99,11 @@ export class HelixProject extends BaseProject {
|
|
|
99
99
|
return this;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
withPreferPlainHtml(value) {
|
|
103
|
+
this._preferPlainHtml = value;
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
|
|
102
107
|
get proxyUrl() {
|
|
103
108
|
return this._proxyUrl;
|
|
104
109
|
}
|
|
@@ -152,6 +157,7 @@ export class HelixProject extends BaseProject {
|
|
|
152
157
|
if (this._htmlFolder) {
|
|
153
158
|
const mount = this._htmlMount || `/${this._htmlFolder}`;
|
|
154
159
|
this._server.withHtmlFolder(this._htmlFolder, mount);
|
|
160
|
+
this._server.withPreferPlainHtml(this._preferPlainHtml);
|
|
155
161
|
}
|
|
156
162
|
await super.init();
|
|
157
163
|
this._indexer = new Indexer()
|
|
@@ -26,6 +26,11 @@ import { transformContentMetadataHtml } from '../content/content-metadata-html.j
|
|
|
26
26
|
const LOGIN_ROUTE = '/.aem/cli/login';
|
|
27
27
|
const LOGIN_ACK_ROUTE = '/.aem/cli/login/ack';
|
|
28
28
|
|
|
29
|
+
// HTML folder candidate extensions, in lookup order.
|
|
30
|
+
// First entry takes precedence when multiple candidates exist on disk.
|
|
31
|
+
const HTML_FOLDER_EXTENSIONS = ['.html', '.plain.html'];
|
|
32
|
+
const HTML_FOLDER_EXTENSIONS_PREFER_PLAIN = [...HTML_FOLDER_EXTENSIONS].reverse();
|
|
33
|
+
|
|
29
34
|
/**
|
|
30
35
|
* @param {import('express').Request} req
|
|
31
36
|
* @param {import('./RequestContext.js').default} ctx
|
|
@@ -92,6 +97,11 @@ export class HelixServer extends BaseServer {
|
|
|
92
97
|
return this;
|
|
93
98
|
}
|
|
94
99
|
|
|
100
|
+
withPreferPlainHtml(value) {
|
|
101
|
+
this._preferPlainHtml = value;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
95
105
|
get mountPrefix() {
|
|
96
106
|
return this._mountPrefix;
|
|
97
107
|
}
|
|
@@ -200,59 +210,54 @@ export class HelixServer extends BaseServer {
|
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
/**
|
|
203
|
-
* Resolves
|
|
213
|
+
* Resolves a candidate file inside the HTML folder, returning its absolute path
|
|
214
|
+
* if it exists and passes the security check, or null otherwise.
|
|
204
215
|
* @param {string} relativePath path relative to HTML folder
|
|
205
|
-
* @returns {Promise<
|
|
216
|
+
* @returns {Promise<string|null>} absolute path, or null if missing/invalid
|
|
206
217
|
*/
|
|
207
|
-
async
|
|
208
|
-
|
|
209
|
-
if (relativePath.includes('/../')) {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Don't process if it already has an extension
|
|
214
|
-
if (relativePath.includes('.')) {
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Try .html first
|
|
219
|
-
const htmlFile = path.resolve(
|
|
218
|
+
async resolveCandidate(relativePath) {
|
|
219
|
+
const file = path.resolve(
|
|
220
220
|
this._project.directory,
|
|
221
221
|
this._htmlFolder,
|
|
222
|
-
|
|
222
|
+
relativePath,
|
|
223
223
|
);
|
|
224
224
|
|
|
225
|
-
if (!utils.validatePathSecurity(
|
|
225
|
+
if (!utils.validatePathSecurity(file, this._project.directory)) {
|
|
226
226
|
return null;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
try {
|
|
230
|
-
const stats = await lstat(
|
|
230
|
+
const stats = await lstat(file);
|
|
231
231
|
if (stats.isFile()) {
|
|
232
|
-
return
|
|
232
|
+
return file;
|
|
233
233
|
}
|
|
234
234
|
} catch (e) {
|
|
235
|
-
//
|
|
235
|
+
// not found
|
|
236
236
|
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
237
239
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (
|
|
240
|
+
/**
|
|
241
|
+
* Resolves which HTML file to serve from the HTML folder
|
|
242
|
+
* @param {string} relativePath path relative to HTML folder
|
|
243
|
+
* @returns {Promise<{file: string, isPlain: boolean}|null>} resolved file info or null
|
|
244
|
+
*/
|
|
245
|
+
async resolveHtmlFolderFile(relativePath) {
|
|
246
|
+
// Don't process if it already has an extension
|
|
247
|
+
if (relativePath.includes('.')) {
|
|
246
248
|
return null;
|
|
247
249
|
}
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
const candidates = this._preferPlainHtml
|
|
252
|
+
? HTML_FOLDER_EXTENSIONS_PREFER_PLAIN
|
|
253
|
+
: HTML_FOLDER_EXTENSIONS;
|
|
254
|
+
|
|
255
|
+
for (const ext of candidates) {
|
|
256
|
+
// eslint-disable-next-line no-await-in-loop
|
|
257
|
+
const file = await this.resolveCandidate(`${relativePath}${ext}`);
|
|
258
|
+
if (file) {
|
|
259
|
+
return { file, isPlain: ext === '.plain.html' };
|
|
253
260
|
}
|
|
254
|
-
} catch (e) {
|
|
255
|
-
// Neither exists
|
|
256
261
|
}
|
|
257
262
|
|
|
258
263
|
return null;
|
package/src/up.cmd.js
CHANGED
|
@@ -65,6 +65,11 @@ export default class UpCommand extends AbstractServerCommand {
|
|
|
65
65
|
return this;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
withPreferPlainHtml(value) {
|
|
69
|
+
this._preferPlainHtml = value;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
68
73
|
async doStop() {
|
|
69
74
|
await super.doStop();
|
|
70
75
|
if (this._watcher) {
|
|
@@ -118,7 +123,8 @@ export default class UpCommand extends AbstractServerCommand {
|
|
|
118
123
|
.withSiteToken(this._siteToken)
|
|
119
124
|
.withCookies(this._cookies)
|
|
120
125
|
.withHtmlFolder(this._htmlFolder)
|
|
121
|
-
.withHtmlMount(this._htmlMount)
|
|
126
|
+
.withHtmlMount(this._htmlMount)
|
|
127
|
+
.withPreferPlainHtml(this._preferPlainHtml);
|
|
122
128
|
|
|
123
129
|
this.log.info(chalk`{yellow ___ ________ ___ __ __ v${pkgJson.version}}`);
|
|
124
130
|
this.log.info(chalk`{yellow / | / ____/ |/ / _____(_)___ ___ __ __/ /___ _/ /_____ _____}`);
|
package/src/up.js
CHANGED
|
@@ -125,6 +125,12 @@ export default function up() {
|
|
|
125
125
|
describe: 'URL path where html-folder files are served (e.g., / for root). Defaults to /FOLDER.',
|
|
126
126
|
type: 'string',
|
|
127
127
|
})
|
|
128
|
+
.option('prefer-plain-html', {
|
|
129
|
+
alias: 'preferPlainHtml',
|
|
130
|
+
describe: 'When --html-folder is set, prefer <stem>.plain.html over <stem>.html if both exist.',
|
|
131
|
+
type: 'boolean',
|
|
132
|
+
default: false,
|
|
133
|
+
})
|
|
128
134
|
|
|
129
135
|
.help();
|
|
130
136
|
},
|
|
@@ -153,6 +159,7 @@ export default function up() {
|
|
|
153
159
|
.withCookies(argv.cookies)
|
|
154
160
|
.withHtmlFolder(argv.htmlFolder)
|
|
155
161
|
.withHtmlMount(argv.htmlMount)
|
|
162
|
+
.withPreferPlainHtml(argv.preferPlainHtml)
|
|
156
163
|
.run();
|
|
157
164
|
},
|
|
158
165
|
};
|