diff --git a/blocks/edit/da-content/da-content.js b/blocks/edit/da-content/da-content.js index 142b279b2..c59ccf7a6 100644 --- a/blocks/edit/da-content/da-content.js +++ b/blocks/edit/da-content/da-content.js @@ -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 }, @@ -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`
${this._editorLoaded ? html` .metadata'); // Check if the metadata div has no additional classes (or doesn't exist) diff --git a/blocks/shared/prose2aem.js b/blocks/shared/prose2aem.js index 5afbb3825..c769d958a 100644 --- a/blocks/shared/prose2aem.js +++ b/blocks/shared/prose2aem.js @@ -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'); @@ -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'); @@ -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'); @@ -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); @@ -264,7 +265,7 @@ export default function prose2aem(editor, livePreview, isFragment = false, lockd `; - if (livePreview && lockdownImages) { + if (livePreview) { html = html.replaceAll('https://content.da.live/', '/'); html = html.replaceAll('https://stage-content.da.live/', '/'); } @@ -272,7 +273,7 @@ export default function prose2aem(editor, livePreview, isFragment = false, lockd return html; } -export function getHtmlWithCursor(view, lockdownImages = false) { +export function getHtmlWithCursor(view) { const { selection } = view.state; const cursorPos = selection.from; @@ -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); } diff --git a/blocks/shared/utils.js b/blocks/shared/utils.js index 9cc5d33d7..9879022e4 100644 --- a/blocks/shared/utils.js +++ b/blocks/shared/utils.js @@ -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} True if lockdownImages flag is enabled, false otherwise + * @deprecated */ export async function checkLockdownImages(owner) { try { diff --git a/test/unit/blocks/shared/utils.test.js b/test/unit/blocks/shared/utils.test.js index 2b83e9481..00e405d13 100644 --- a/test/unit/blocks/shared/utils.test.js +++ b/test/unit/blocks/shared/utils.test.js @@ -6,7 +6,6 @@ import { saveToDa, getSheetByIndex, getFirstSheet, - checkLockdownImages, delay, getSidekickConfig, sanitizeName, @@ -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';