Skip to content

Commit

Permalink
Feature/picture info (#9)
Browse files Browse the repository at this point in the history
* Adding picture info.

* Add picture info test

* Update ReadMe
  • Loading branch information
ErikHen authored Oct 14, 2022
1 parent 40d34ae commit b4fc5aa
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 10 deletions.
27 changes: 21 additions & 6 deletions PictureRenderer/Picture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ public static string Render(string imagePath, PictureProfileBase profile, string
{
sourceElementWebp = RenderSourceElement(pictureData, ImageFormat.Webp);
}

var imgElement = RenderImgElement(pictureData, profile, lazyLoading, imgWidth);

//Webp source element must be rendered first. Browser selects the first version it supports.
return $"<picture>{sourceElementWebp}{sourceElement}{imgElement}</picture>";
var imgElement = RenderImgElement(pictureData, profile, lazyLoading, imgWidth);
var pictureElement = $"<picture>{sourceElementWebp}{sourceElement}{imgElement}</picture>"; //Webp source element must be rendered first. Browser selects the first version it supports.
var infoElements = RenderInfoElements(profile, pictureData);

return $"{pictureElement}{infoElements}";
}

/// <summary>
Expand All @@ -74,18 +75,21 @@ public static string Render(string[] imagePaths, PictureProfileBase profile, str
var pictureData = PictureUtils.GetMultiImagePictureData(imagePaths, profile, altText, focalPoints, cssClass);
var sourceElements = RenderSourceElementsForMultiImage(pictureData);
var imgElement = RenderImgElement(pictureData, profile, lazyLoading);
var pictureElement = $"<picture>{sourceElements}{imgElement}</picture>";
var infoElements = RenderInfoElements(profile, pictureData);

return $"<picture>{sourceElements}{imgElement}</picture>";
return $"{pictureElement}{infoElements}";
}

private static string RenderImgElement(PictureData pictureData, PictureProfileBase profile, LazyLoading lazyLoading, string imgWidth = "")
{
var idAttribute = string.IsNullOrEmpty(pictureData.UniqueId) ? string.Empty : $" id=\"{pictureData.UniqueId}\"";
var widthAndHeightAttributes = GetImgWidthAndHeightAttributes(profile, imgWidth);
var loadingAttribute = lazyLoading == LazyLoading.Browser ? "loading=\"lazy\" " : string.Empty;
var classAttribute = string.IsNullOrEmpty(pictureData.CssClass) ? string.Empty : $"class=\"{HttpUtility.HtmlEncode(pictureData.CssClass)}\"";
var decodingAttribute = profile.ImageDecoding == ImageDecoding.None ? string.Empty : $"decoding=\"{Enum.GetName(typeof(ImageDecoding), profile.ImageDecoding)?.ToLower()}\" ";

return $"<img alt=\"{HttpUtility.HtmlEncode(pictureData.AltText)}\" src=\"{pictureData.ImgSrc}\" {widthAndHeightAttributes}{loadingAttribute}{decodingAttribute}{classAttribute}/>";
return $"<img{idAttribute} alt=\"{HttpUtility.HtmlEncode(pictureData.AltText)}\" src=\"{pictureData.ImgSrc}\" {widthAndHeightAttributes}{loadingAttribute}{decodingAttribute}{classAttribute}/>";
}

private static string GetImgWidthAndHeightAttributes(PictureProfileBase profile, string imgWidth)
Expand Down Expand Up @@ -134,5 +138,16 @@ private static string RenderSourceElementsForMultiImage(MediaImagesPictureData p

return sourceElementsBuilder.ToString();
}

private static string RenderInfoElements(PictureProfileBase pictureProfile, PictureData pictureData)
{
if (!pictureProfile.ShowInfo)
{
return string.Empty;
}
var infoDiv = $"<div id=\"pinfo{pictureData.UniqueId}\" style=\"position: absolute; margin-top:-60px; padding:0 5px 2px 5px; font-size:0.8rem; text-align:left; background-color:rgba(255, 255, 255, 0.8);\"></div>";
var script =$"<script type=\"text/javascript\"> window.addEventListener(\"load\",function () {{ const pictureInfo = document.getElementById('pinfo{pictureData.UniqueId}'); var image = document.getElementById('{pictureData.UniqueId}'); pictureInfo.innerText = format{pictureData.UniqueId}(image.currentSrc); image.onload = function () {{ pictureInfo.innerText = format{pictureData.UniqueId}(image.currentSrc); }}; function format{pictureData.UniqueId}(input) {{ return input.split('/').pop().replace('?', '\\n').replaceAll('&', ', ').replace('%2c', ',').replace('rxy', 'focal point'); }} }}, false);</script>";
return "\n" + infoDiv + "\n" + script;
}
}
}
5 changes: 4 additions & 1 deletion PictureRenderer/PictureData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ internal class PictureData
//public string ImgSrcLowQuality { get; set; }
public string AltText { get; set; }
public string CssClass { get; set; }

/// <summary>
/// Id used when rendering picture info.
/// </summary>
public string UniqueId { get; set; }
}
}
2 changes: 1 addition & 1 deletion PictureRenderer/PictureRenderer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>3.4</Version>
<Version>3.5</Version>
<Authors>Erik Henningson</Authors>
<Company />
<Product />
Expand Down
6 changes: 4 additions & 2 deletions PictureRenderer/PictureUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public static PictureData GetPictureData(string imagePath, PictureProfileBase pr
ImgSrc = BuildQueryString(uri, profile, profile.FallbackWidth, string.Empty, focalPoint),
CssClass = cssClass,
SrcSet = BuildSrcSet(uri, profile, string.Empty, focalPoint),
SizesAttribute = string.Join(", ", profile.Sizes)
SizesAttribute = string.Join(", ", profile.Sizes),
UniqueId = profile.ShowInfo ? Guid.NewGuid().ToString("n").Substring(0, 10) : string.Empty
};

if (ShouldCreateWebp(profile, uri))
Expand Down Expand Up @@ -83,7 +84,8 @@ public static MediaImagesPictureData GetMultiImagePictureData(string[] imagePath
MediaImages = mediaImagePaths,
AltText = altText,
ImgSrc = BuildQueryString(fallbackImageUri, profile, profile.FallbackWidth, string.Empty, fallbackImageFocalPoint),
CssClass = cssClass
CssClass = cssClass,
UniqueId = profile.ShowInfo ? Guid.NewGuid().ToString("n").Substring(0, 10) : string.Empty
};

return pData;
Expand Down
4 changes: 4 additions & 0 deletions PictureRenderer/Profiles/PictureProfileBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ public int FallbackWidth
/// </summary>
public ImageDecoding ImageDecoding {get; set;}

public bool ShowInfo { get; set; }


protected PictureProfileBase()
{
Quality = 80;
CreateWebpForFormat = new string[] {ImageFormat.Jpeg};
ImageDecoding = ImageDecoding.Async;
ShowInfo = false;
}
}
}
21 changes: 21 additions & 0 deletions PictureRendererTests/PictureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,27 @@ public void RenderWithDomainTest()
Assert.Equal(expected, result);
}

[Fact()]
public void RenderWithInfoTest()
{
const string expectedStart = "<picture><source srcset=\"/myImage.jpg?width=150&height=150&quality=80 150w, /myImage.jpg?width=300&height=300&quality=80 300w\" sizes=\"150px\" /><img id=\"";
const string expectedContains1 = "<div id=\"pinfo";
const string expectedContains2 = "style=\"position: absolute; margin-top:-60px; padding:0 5px 2px 5px; font-size:0.8rem; text-align:left; background-color:rgba(255, 255, 255, 0.8);\"></div>";
const string expectedContains3 = "window.addEventListener(\"load\",function () { const pictureInfo = document.getElementById('";
const string expectedEnd = "(input) { return input.split('/').pop().replace('?', '\\n').replaceAll('&', ', ').replace('%2c', ',').replace('rxy', 'focal point'); } }, false);</script>";
var profile = GetTestImageProfile();
profile.ShowInfo = true;
profile.CreateWebpForFormat = null;

var result = PictureRenderer.Picture.Render("/myImage.jpg", profile);

Assert.StartsWith(expectedStart, result);
Assert.Contains(expectedContains1, result);
Assert.Contains(expectedContains2, result);
Assert.Contains(expectedContains3, result);
Assert.EndsWith(expectedEnd, result);
}

private static ImageSharpProfile GetTestImageProfile()
{
//use this to test with both single and multiple images
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public static class PictureProfiles
* **FallbackWidth (optional)** – This image width will be used in browsers that don’t support the picture element. Will use the largest width if not set.
* **ImageDecoding (optional)** - Value for img element `decoding` attribute. Default value: `async`.
* **ImgWidthHeight (optional)** - If true, `width` and `height` attributes will be rendered on the img element.
* **ShowInfo (optional)** - If true, an overlay will show info about the currently selected image.

### Render picture element
Render the picture element by calling `Picture.Render`
Expand Down Expand Up @@ -118,7 +119,14 @@ Basic Blazor sample
See also [sample projects](https://github.com/ErikHen/PictureRenderer.Samples).
<br><br>

### How to see that it actually works
If you set ```ShowInfo = true``` in the picture profile, an overlay with information about the currently selected image will be rendered.<br>
You can see that different images are selected for different devices and screen sizes. Note that the Chrome (Chromium based) browser will not select a smaller image if a larger one is already downloaded. It may be easier to see the actual behaviour when using e.g. Firefox.
<br>
This setting should of course never be true in your live/production environment, it's only meant for testing.

## Version history
* **3.5** Possible to show info about the currently selected image.
* **3.4** Keep domain in image urls (earlier it always returned an absolute path).
* **3.3.1** Add space between attributes.
* **3.3** Adding possibility to set width attribute on img element. Needed for rare edge case in Optimizely CMS.
Expand Down

0 comments on commit b4fc5aa

Please sign in to comment.