@adobe/aem-cli 16.19.11 → 16.19.13

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,19 @@
1
+ ## [16.19.13](https://github.com/adobe/helix-cli/compare/v16.19.12...v16.19.13) (2026-06-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **content:** normalize org/repo to lowercase in aem content clone ([#2735](https://github.com/adobe/helix-cli/issues/2735)) ([1bba483](https://github.com/adobe/helix-cli/commit/1bba48323f19024af5682e2c751bb073bd91b4ce))
7
+
8
+ ## [16.19.12](https://github.com/adobe/helix-cli/compare/v16.19.11...v16.19.12) (2026-06-03)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * extract main innerHTML for .plain.html fallback and improve test fixture ([e49ca05](https://github.com/adobe/helix-cli/commit/e49ca059f67da164ff20ad549dbd40590797f911))
14
+ * **lint:** fix curly brace style and install missing dependencies ([e138bf0](https://github.com/adobe/helix-cli/commit/e138bf00f1da5c2c8f542fe56a3a8a86ee63a70c))
15
+ * properly serve .plain.html requests for documents in local content directory ([89d12d5](https://github.com/adobe/helix-cli/commit/89d12d574e7e8a143f32973c4f319f814d814099))
16
+
1
17
  ## [16.19.11](https://github.com/adobe/helix-cli/compare/v16.19.10...v16.19.11) (2026-05-26)
2
18
 
3
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/aem-cli",
3
- "version": "16.19.11",
3
+ "version": "16.19.13",
4
4
  "description": "AEM CLI",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -18,7 +18,8 @@
18
18
  "@web/test-runner": "0.20.2",
19
19
  "@web/test-runner-junit-reporter": "0.8.0",
20
20
  "@web/test-runner-mocha": "0.9.0",
21
- "@web/test-runner-playwright": "0.11.1"
21
+ "@web/test-runner-playwright": "0.11.1",
22
+ "playwright": "1.60.0"
22
23
  }
23
24
  },
24
25
  "node_modules/@adobe/eslint-config-helix": {
@@ -5420,13 +5421,13 @@
5420
5421
  }
5421
5422
  },
5422
5423
  "node_modules/playwright": {
5423
- "version": "1.56.0",
5424
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.0.tgz",
5425
- "integrity": "sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==",
5424
+ "version": "1.60.0",
5425
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz",
5426
+ "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==",
5426
5427
  "dev": true,
5427
5428
  "license": "Apache-2.0",
5428
5429
  "dependencies": {
5429
- "playwright-core": "1.56.0"
5430
+ "playwright-core": "1.60.0"
5430
5431
  },
5431
5432
  "bin": {
5432
5433
  "playwright": "cli.js"
@@ -5439,9 +5440,9 @@
5439
5440
  }
5440
5441
  },
5441
5442
  "node_modules/playwright-core": {
5442
- "version": "1.56.0",
5443
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.0.tgz",
5444
- "integrity": "sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==",
5443
+ "version": "1.60.0",
5444
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz",
5445
+ "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==",
5445
5446
  "dev": true,
5446
5447
  "license": "Apache-2.0",
5447
5448
  "bin": {
@@ -8,7 +8,7 @@
8
8
  "lint": "eslint .",
9
9
  "test": "web-test-runner",
10
10
  "test:watch": "web-test-runner --watch",
11
- "postinstall": "npm run copy-vendor && npx playwright install",
11
+ "postinstall": "npm run copy-vendor",
12
12
  "copy-vendor": "node scripts/copy-vendor.js"
13
13
  },
14
14
  "devDependencies": {
@@ -18,7 +18,8 @@
18
18
  "@web/test-runner": "0.20.2",
19
19
  "@web/test-runner-playwright": "0.11.1",
20
20
  "@web/test-runner-junit-reporter": "0.8.0",
21
- "@web/test-runner-mocha": "0.9.0"
21
+ "@web/test-runner-mocha": "0.9.0",
22
+ "playwright": "1.60.0"
22
23
  },
23
24
  "dependencies": {
24
25
  "livereload-js": "4.0.2"
@@ -101,14 +101,14 @@ export default class CloneCommand {
101
101
  throw new Error('Clone root path was not set (internal error).');
102
102
  }
103
103
 
104
- // 1. Resolve org/repo from git remote
104
+ // 1. Resolve owner/repo from git remote
105
105
  const originUrl = await GitUtils.getOriginURL(this._dir);
106
106
  if (!originUrl) {
107
107
  throw new Error('No git remote found. Run `aem content clone` inside an AEM project directory.');
108
108
  }
109
- const org = originUrl.owner;
110
- const { repo } = originUrl;
111
- log.info(`Cloning content from da.live: ${org}/${repo}${this._rootPath === '/' ? '' : ` @ ${this._rootPath}`}`);
109
+ const owner = originUrl.owner.toLowerCase();
110
+ const repo = originUrl.repo.toLowerCase();
111
+ log.info(`Cloning content from da.live: ${owner}/${repo}${this._rootPath === '/' ? '' : ` @ ${this._rootPath}`}`);
112
112
 
113
113
  // 2. Ensure target path is available (do not create content/ until after file count is known)
114
114
  const contentDir = path.resolve(this._dir, CONTENT_DIR);
@@ -126,7 +126,7 @@ export default class CloneCommand {
126
126
  const client = new DaClient(token);
127
127
  log.info('Fetching file list...');
128
128
  const showDiscoveryProgress = process.stdout.isTTY;
129
- const files = await client.listAll(org, repo, this._rootPath, showDiscoveryProgress
129
+ const files = await client.listAll(owner, repo, this._rootPath, showDiscoveryProgress
130
130
  ? (n) => {
131
131
  process.stdout.write(`\r ${n} file(s) discovered so far...`);
132
132
  }
@@ -148,15 +148,15 @@ export default class CloneCommand {
148
148
  const downloadResults = await processQueue(
149
149
  files,
150
150
  async (file) => {
151
- const prefix = `/${org}/${repo}`;
151
+ const prefix = `/${owner}/${repo}`;
152
152
  if (!file.path.startsWith(prefix)) {
153
- log.warn(` skip (unexpected path, missing org/repo prefix): ${file.path}`);
153
+ log.warn(` skip (unexpected path, missing owner/repo prefix): ${file.path}`);
154
154
  return { status: 404 };
155
155
  }
156
156
  const daPath = file.path.slice(prefix.length) || '/';
157
157
  const localPath = path.join(contentDir, ...daPath.split('/').filter(Boolean));
158
158
  try {
159
- const res = await client.getSource(org, repo, daPath);
159
+ const res = await client.getSource(owner, repo, daPath);
160
160
  if (!res) {
161
161
  log.warn(` skip (not found): ${daPath}`);
162
162
  return { status: 404 };
@@ -195,7 +195,7 @@ export default class CloneCommand {
195
195
  await git.commit({
196
196
  fs,
197
197
  dir: contentDir,
198
- message: `clone: ${org}/${repo}${this._rootPath === '/' ? '' : ` (${this._rootPath})`}`,
198
+ message: `clone: ${owner}/${repo}${this._rootPath === '/' ? '' : ` (${this._rootPath})`}`,
199
199
  author: GIT_AUTHOR,
200
200
  });
201
201
  const headOid = await git.resolveRef({ fs, dir: contentDir, ref: 'HEAD' });
@@ -203,7 +203,7 @@ export default class CloneCommand {
203
203
 
204
204
  // 8. Write config (not tracked by git)
205
205
  await fse.writeJson(path.join(contentDir, CONFIG_FILE), {
206
- org,
206
+ owner,
207
207
  repo,
208
208
  rootPath: this._rootPath,
209
209
  }, { spaces: 2 });
@@ -459,7 +459,26 @@ export class HelixServer extends BaseServer {
459
459
  try {
460
460
  if (contentFilePath.endsWith('.html')) {
461
461
  // readFile throws EISDIR for directories and ENOENT for missing files
462
- let htmlContent = await readFile(contentFilePath, 'utf-8');
462
+ // .plain.html is a virtual URL convention — AEM never stores .plain.html files,
463
+ // so always read the corresponding .html file and serve the <main> fragment.
464
+ const isPlainFallback = contentFilePath.endsWith('.plain.html');
465
+ const servedFilePath = isPlainFallback
466
+ ? `${contentFilePath.slice(0, -'.plain.html'.length)}.html`
467
+ : contentFilePath;
468
+ let htmlContent = await readFile(servedFilePath, 'utf-8');
469
+ if (isPlainFallback) {
470
+ if (liveReload) {
471
+ liveReload.registerFile(ctx.requestId, servedFilePath);
472
+ }
473
+ const fragment = utils.extractMainContent(htmlContent);
474
+ res.set({
475
+ 'content-type': 'text/html; charset=utf-8',
476
+ 'access-control-allow-origin': '*',
477
+ });
478
+ res.send(fragment);
479
+ log.debug(`${pfx}served from ${CONTENT_DIR}/: ${ctx.path}`);
480
+ return;
481
+ }
463
482
  const absolutePageUrl = absolutePageUrlFromRequest(req, ctx);
464
483
  if (this._project.metadataSheet) {
465
484
  this._project.metadataSheet.setCookie(req.headers.cookie || '');
@@ -19,11 +19,14 @@ import { fileURLToPath } from 'url';
19
19
  import cookie from 'cookie';
20
20
  import { unified } from 'unified';
21
21
  import rehypeParse from 'rehype-parse';
22
+ import { select } from 'hast-util-select';
23
+ import { toHtml } from 'hast-util-to-html';
22
24
  import { getFetch } from '../fetch-utils.js';
23
25
 
24
26
  // Load console interceptor script at startup
25
27
  // eslint-disable-next-line no-underscore-dangle
26
28
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
29
+ const htmlParser = unified().use(rehypeParse);
27
30
  const CONSOLE_INTERCEPTOR = readFileSync(
28
31
  path.join(__dirname, '../../packages/browser-injectables/src/console-interceptor.js'),
29
32
  'utf-8',
@@ -787,6 +790,21 @@ window.LiveReloadOptions = {
787
790
  const fullHead = headHtml + metaTags;
788
791
  return `<html><head>${fullHead}</head><body><header></header><main>${content}</main><footer></footer></body></html>`;
789
792
  },
793
+
794
+ /**
795
+ * Extracts the innerHTML of the <main> element from a full HTML document.
796
+ * Returns the original content unchanged if no <main> is found.
797
+ * @param {string} html full HTML document
798
+ * @returns {string} innerHTML of <main>, or original html if no <main> present
799
+ */
800
+ extractMainContent(html) {
801
+ const ast = htmlParser.parse(html);
802
+ const main = select('main', ast);
803
+ if (!main) {
804
+ return html;
805
+ }
806
+ return main.children.map((child) => toHtml(child)).join('');
807
+ },
790
808
  };
791
809
 
792
810
  export default Object.freeze(utils);