Skip to content

Commit

Permalink
Synch Changes from dev branch:
Browse files Browse the repository at this point in the history
:
  • Loading branch information
Satya Deep Maheshwari committed Jan 7, 2024
1 parent b24fda6 commit 5f98c82
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 3 deletions.
45 changes: 45 additions & 0 deletions EXTERNAL_IMAGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Using images from external URLs in AEM Franklin pages

## Introduction
This document explains a mechanism for getting images served from external URLs on AEM Franklin pages. You may find this useful if you want to have your images served from an external assets repository.

## Process
During the page authoring process, the author has to specify the external URL from which the image is served. This is done by placing external image links containing the hyperlinked publicly accessible image URLs on the Word/Google Document. The image links are then replaced with the actual images during the page rendering process.

### Note for site authors
Here's [an example page and document](https://ext-images--franklin-assets-selector--hlxsites.hlx.page/external-images-example?view-doc-source=true) that shows how to use external images in AEM Franklin pages.
You can specify external images by just copying and pasting the image URL in the Word/Google Document. The image URL must be hyperlinked. If the hyperlink has an image file extension, it will be treated as an external image. If the hyperlink does not have an image file extension, it will be treated as a regular hyperlink.
Alternatively, you can also explicitly specify an external image marker and adding the external image url as a hyperlink in it.
The above [example page](https://ext-images--franklin-assets-selector--hlxsites.hlx.page/external-images-example?view-doc-source=true) demonstrates both the approaches.

### Note for site developers
Anchor tags get treated as external images if their `textContent` is same as their `href` attribute and the URL specified in `href` is of an image file extension. For e.g. `'jpg', 'jpeg', 'png', 'gif', 'webp'`. Web optimized image formats such as `webp` should be preferred. You can find the implementation of this [here](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L105-L110)

Alternatively, an *image marker* text can be used to explicitly indicate external images. This is a pre-configured value. You can configure it [here](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L227).


Also note that for creating optimized `picture` tags for external images, you must override `createOptimizedPicture` function. You can find a sample overidden implementation of `createOptimizedPicture` [here](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L142-L182).

To summarize, most of the logic for this [is here](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L69-L218) and trigger point for it starts with `decorateExternalImages`. For e.g. [here with an implict external image decoration](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L229-L230).

```
export function decorateMain(main) {
// decorate external images with implicit external image detection
decorateExternalImages(main);
...
}
```

And [here with an explicit external image marker](https://github.com/hlxsites/franklin-assets-selector/blob/9145aeac55512ec199152065b16db6c24cea3421/scripts/scripts.js#L226-L227).
```
export function decorateMain(main) {
// decorate external images with explicit external image marker
decorateExternalImages(main, '//External Image//');
...
}
```

## How does this work?
During the page rendering process, the frontend code replaces the anchor tags identified as exteernal images on the page with the `picture` tags with `src`/`srcset` attributes set as the external image's url as specified in the external image link placed on the Word / Google Document during the page authoring process.

Authors can optionally specify query paramaters in the hyperlinked external url and they would be retained in the `picture` tag's `src`/`srcset` attributes. These are useful for specifying image delivery parameters such as image width, height, format, etc. as understood by the external image delivery service.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Your Project's Title...
Your project's description...
# AEM Asset Selector for Franklin Authoring
Integration between AEM Asset Selector and AEM Franklin to make AEM assets available in Franklin site authoring.

# High level flow

[Link to Diagram Source](https://lucid.app/lucidchart/d6db1b7d-144f-4ac9-94a2-fce760ed2ca4/edit?viewport_loc=-368%2C-403%2C1899%2C1069%2C0_0&invitationId=inv_cd6848d0-dfc0-4be9-b0cb-3cae5a1ba757)

![High Level Flow](/resources/using-asset-selector-with-franklin.jpeg)

## Environments
- Preview: https://main--{repo}--{owner}.hlx.page/
Expand Down
65 changes: 65 additions & 0 deletions blocks/embed/embed.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
main .embed {
width: unset;
text-align: center;
max-width: 800px;
margin: 32px auto;
}

main .embed > div {
display: flex;
justify-content: center;
}

main .embed.embed-twitter .twitter-tweet-rendered {
margin-left: auto;
margin-right: auto;
}

main .embed .embed-placeholder {
width: 100%;
aspect-ratio: 16 / 9;
position: relative;
}

main .embed .embed-placeholder > * {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}

main .embed .embed-placeholder picture img {
width: 100%;
height: 100%;
object-fit: cover;
}

main .embed .embed-placeholder-play button {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(3);
width: 22px;
height: 22px;
border: 2px solid;
border-radius: 20px;
padding: 0;
}

main .embed .embed-placeholder-play button::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
width: 0;
height: 10px;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid;
top: 4px;
left: 7px;
}
113 changes: 113 additions & 0 deletions blocks/embed/embed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Embed Block
* Show videos and social posts directly on your page
* https://www.hlx.live/developer/block-collection/embed
*/

const loadScript = (url, callback, type) => {
const head = document.querySelector('head');
const script = document.createElement('script');
script.src = url;
if (type) {
script.setAttribute('type', type);
}
script.onload = callback;
head.append(script);
return script;
};

const getDefaultEmbed = (url) => `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
<iframe src="${url.href}" style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;" allowfullscreen=""
scrolling="no" allow="encrypted-media" title="Content from ${url.hostname}" loading="lazy">
</iframe>
</div>`;

const embedYoutube = (url, autoplay) => {
const usp = new URLSearchParams(url.search);
const suffix = autoplay ? '&muted=1&autoplay=1' : '';
let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : '';
const embed = url.pathname;
if (url.origin.includes('youtu.be')) {
[, vid] = url.pathname.split('/');
}
const embedHTML = `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
<iframe src="https://www.youtube.com${vid ? `/embed/${vid}?rel=0&v=${vid}${suffix}` : embed}" style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
allow="autoplay; fullscreen; picture-in-picture; encrypted-media; accelerometer; gyroscope; picture-in-picture" allowfullscreen="" scrolling="no" title="Content from Youtube" loading="lazy"></iframe>
</div>`;
return embedHTML;
};

const embedVimeo = (url, autoplay) => {
const [, video] = url.pathname.split('/');
const suffix = autoplay ? '?muted=1&autoplay=1' : '';
const embedHTML = `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
<iframe src="https://player.vimeo.com/video/${video}${suffix}"
style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen
title="Content from Vimeo" loading="lazy"></iframe>
</div>`;
return embedHTML;
};

const embedTwitter = (url) => {
const embedHTML = `<blockquote class="twitter-tweet"><a href="${url.href}"></a></blockquote>`;
loadScript('https://platform.twitter.com/widgets.js');
return embedHTML;
};

const loadEmbed = (block, link, autoplay) => {
if (block.classList.contains('embed-is-loaded')) {
return;
}

const EMBEDS_CONFIG = [
{
match: ['youtube', 'youtu.be'],
embed: embedYoutube,
},
{
match: ['vimeo'],
embed: embedVimeo,
},
{
match: ['twitter'],
embed: embedTwitter,
},
];

const config = EMBEDS_CONFIG.find((e) => e.match.some((match) => link.includes(match)));
const url = new URL(link);
if (config) {
block.innerHTML = config.embed(url, autoplay);
block.classList = `block embed embed-${config.match[0]}`;
} else {
block.innerHTML = getDefaultEmbed(url);
block.classList = 'block embed';
}
block.classList.add('embed-is-loaded');
};

export default function decorate(block) {
const placeholder = block.querySelector('picture');
const link = block.querySelector('a').href;
block.textContent = '';

if (placeholder) {
const wrapper = document.createElement('div');
wrapper.className = 'embed-placeholder';
wrapper.innerHTML = '<div class="embed-placeholder-play"><button title="Play"></button></div>';
wrapper.prepend(placeholder);
wrapper.addEventListener('click', () => {
loadEmbed(block, link, true);
});
block.append(wrapper);
} else {
const observer = new IntersectionObserver((entries) => {
if (entries.some((e) => e.isIntersecting)) {
observer.disconnect();
loadEmbed(block, link);
}
});
observer.observe(block);
}
}
2 changes: 1 addition & 1 deletion fstab.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
mountpoints:
/: https://drive.google.com/drive/u/0/folders/1MGzOt7ubUh3gu7zhZIPb7R7dyRzG371j
/: https://adobe.sharepoint.com/:f:/r/sites/HelixProjects/Shared%20Documents/sites/aem-assets
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 5f98c82

Please sign in to comment.