Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions blocks/edit/da-content/da-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export default class DaContent extends LitElement {
permissions: { attribute: false },
proseEl: { attribute: false },
wsProvider: { attribute: false },
lockdownImages: { attribute: false },
_editorLoaded: { state: true },
_showPane: { state: true },
_versionUrl: { state: true },
Expand Down Expand Up @@ -75,11 +74,6 @@ export default class DaContent extends LitElement {
const { owner, repo, previewUrl } = this.details;
const { pathname } = new URL(previewUrl);

// Only use livePreviewUrl if lockdownImages flag is set to true
const displayUrl = this.lockdownImages
? `${getLivePreviewUrl(owner, repo)}${pathname}`
: previewUrl;

return html`
<div class="editor-wrapper">
<da-editor
Expand Down Expand Up @@ -107,9 +101,8 @@ export default class DaContent extends LitElement {
</div>
${this._editorLoaded ? html`
<da-preview
path=${displayUrl}
path="${getLivePreviewUrl(owner, repo)}${pathname}"
.show=${this._showPane === 'preview'}
.lockdownImages=${this.lockdownImages}
class="${this._showPane === 'preview' ? 'is-visible' : ''}"
@close=${this.togglePane}></da-preview>
<da-versions
Expand Down
3 changes: 1 addition & 2 deletions blocks/edit/da-preview/da-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default class DaPreview extends LitElement {
static properties = {
path: { type: String },
show: { attribute: false },
lockdownImages: { attribute: false },
_size: { state: true },
_updating: { state: true },
_message: { state: true },
Expand Down Expand Up @@ -48,7 +47,7 @@ export default class DaPreview extends LitElement {
if (!window.view) return;

// Always cache the body for future use
this.body = getHtmlWithCursor(window.view, this.lockdownImages);
this.body = getHtmlWithCursor(window.view);

// If initialized, send the preview to the iframe
if (this.initialized && this.body) this.sendPreview();
Expand Down
4 changes: 1 addition & 3 deletions blocks/edit/edit.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import getPathDetails from '../shared/pathDetails.js';
import { daFetch, checkLockdownImages, contentLogin, livePreviewLogin } from '../shared/utils.js';
import { daFetch, contentLogin, livePreviewLogin } from '../shared/utils.js';

import './da-title/da-title.js';
import './da-content/da-content.js';
Expand Down Expand Up @@ -49,7 +49,6 @@ async function setUI(el) {
document.title = `Edit ${details.name} - DA`;

const { owner, repo } = details;
const lockdownPromise = checkLockdownImages(owner);
await Promise.all([
contentLogin(owner, repo),
livePreviewLogin(owner, repo),
Expand Down Expand Up @@ -80,7 +79,6 @@ async function setUI(el) {

daTitle.permissions = permissions;
daContent.permissions = permissions;
daContent.lockdownImages = await lockdownPromise;

const metadataEl = doc.querySelector('main > .metadata');
// Check if the metadata div has no additional classes (or doesn't exist)
Expand Down
41 changes: 20 additions & 21 deletions blocks/shared/prose2aem.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function convertBlocks(editor, isFragment = false) {
});
}

function makePictures(editor, live, lockdown) {
function makePictures(editor, live) {
const imgs = editor.querySelectorAll('img');
imgs.forEach((img) => {
img.removeAttribute('contenteditable');
Expand All @@ -82,20 +82,22 @@ function makePictures(editor, live, lockdown) {
if (daCursor) setCursor(daCursor, img);

const clone = img.cloneNode(true);
if (live && lockdown) {
// make images relative to the live preview URL
const source = new URL(clone.src);
if (source.host.endsWith('.da.live')) {
source.pathname = `/${source.pathname
.split('/')
.slice(3) // remove org and site
.join('/')}`;
clone.src = source.toString();
}
}

clone.setAttribute('loading', 'lazy');

if (live && clone.src) {
try {
const source = new URL(clone.src);
if (source.host.endsWith('.da.live')) {
source.pathname = `/${source.pathname
.split('/')
.slice(3) // remove org and site
.join('/')}`;
clone.src = source.toString();
}
} catch {
// src is not an absolute URL, nothing to rewrite
}
}
let pic = document.createElement('picture');

const srcMobile = document.createElement('source');
Expand Down Expand Up @@ -206,10 +208,9 @@ const removeEls = (els) => els.forEach((el) => el.remove());
* @param {HTMLElement} editor the editor dom
* @param {Boolean} livePreview whether or not the target destination is Live Preview
* @param {Boolean} isFragment whether or not the DOM is a fragment
* @param {Boolean} lockdownImages whether or not to make images and content.da.live URLs relative
* @returns AEM-friendly HTML as a text string
*/
export default function prose2aem(editor, livePreview, isFragment = false, lockdownImages = false) {
export default function prose2aem(editor, livePreview, isFragment = false) {
if (!isFragment) editor.removeAttribute('class');

editor.removeAttribute('contenteditable');
Expand Down Expand Up @@ -246,7 +247,7 @@ export default function prose2aem(editor, livePreview, isFragment = false, lockd
parseIcons(editor);
}

makePictures(editor, livePreview, lockdownImages);
makePictures(editor, livePreview);

if (!isFragment) {
makeSections(editor);
Expand All @@ -264,15 +265,15 @@ export default function prose2aem(editor, livePreview, isFragment = false, lockd
</body>
`;

if (livePreview && lockdownImages) {
if (livePreview) {
html = html.replaceAll('https://content.da.live/', '/');
html = html.replaceAll('https://stage-content.da.live/', '/');
}

return html;
}

export function getHtmlWithCursor(view, lockdownImages = false) {
export function getHtmlWithCursor(view) {
const { selection } = view.state;
const cursorPos = selection.from;

Expand Down Expand Up @@ -325,7 +326,5 @@ export function getHtmlWithCursor(view, lockdownImages = false) {
clonedNode.insertBefore(marker, clonedNode.childNodes[offset] || null);
}

// Convert to an HTML string using prose2aem
// Always use livePreview mode, but only lockdown images if lockdownImages is enabled
return prose2aem(editorClone, true, false, lockdownImages);
return prose2aem(editorClone, true);
}
1 change: 1 addition & 0 deletions blocks/shared/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export async function livePreviewLogin(owner, repo) {
* instead of the public preview URL, preventing unauthorized access to images.
* @param {string} owner - The owner identifier
* @returns {Promise<boolean>} True if lockdownImages flag is enabled, false otherwise
* @deprecated
*/
export async function checkLockdownImages(owner) {
try {
Expand Down
66 changes: 0 additions & 66 deletions test/unit/blocks/shared/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
saveToDa,
getSheetByIndex,
getFirstSheet,
checkLockdownImages,
delay,
getSidekickConfig,
sanitizeName,
Expand Down Expand Up @@ -367,71 +366,6 @@ describe('saveToDa', () => {
});
});

describe('checkLockdownImages', () => {
let savedFetch;
let savedLocalStorage;

beforeEach(() => {
savedFetch = window.fetch;
savedLocalStorage = window.localStorage.getItem('nx-ims');
window.localStorage.removeItem('nx-ims');
});

afterEach(() => {
window.fetch = savedFetch;
if (savedLocalStorage) {
window.localStorage.setItem('nx-ims', savedLocalStorage);
} else {
window.localStorage.removeItem('nx-ims');
}
});

it('Returns true when lockdownImages flag is enabled', async () => {
const body = JSON.stringify({ flags: { data: [{ key: 'lockdownImages', value: 'true' }] } });
window.fetch = () => Promise.resolve(new Response(body, { status: 200 }));

const result = await checkLockdownImages('testowner');
expect(result).to.be.true;
});

it('Returns false when lockdownImages flag is not present', async () => {
const body = JSON.stringify({ flags: { data: [{ key: 'otherFlag', value: 'true' }] } });
window.fetch = () => Promise.resolve(new Response(body, { status: 200 }));

const result = await checkLockdownImages('testowner');
expect(result).to.be.false;
});

it('Returns false when lockdownImages value is not true', async () => {
const body = JSON.stringify({ flags: { data: [{ key: 'lockdownImages', value: 'false' }] } });
window.fetch = () => Promise.resolve(new Response(body, { status: 200 }));

const result = await checkLockdownImages('testowner');
expect(result).to.be.false;
});

it('Returns false when flags sheet does not exist', async () => {
window.fetch = () => Promise.resolve(new Response(JSON.stringify({}), { status: 200 }));

const result = await checkLockdownImages('testowner');
expect(result).to.be.false;
});

it('Returns false when config fetch fails', async () => {
window.fetch = () => Promise.resolve(new Response('error', { status: 500 }));

const result = await checkLockdownImages('testowner');
expect(result).to.be.false;
});

it('Returns false when fetch throws', async () => {
window.fetch = () => Promise.reject(new Error('network error'));

const result = await checkLockdownImages('testowner');
expect(result).to.be.false;
});
});

describe('getSidekickConfig', () => {
it('Returns preview and prod when both hosts are available', async () => {
const org = 'org1';
Expand Down
Loading