SourceSet
Represents a useful helper for dealing with source sets.
using AngleSharp.Css.Values;
using AngleSharp.Dom;
using AngleSharp.Extensions;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace AngleSharp.Html
{
internal sealed class SourceSet
{
private sealed class MediaSize
{
public string Media { get; set; }
public string Length { get; set; }
}
private sealed class ImageCandidate
{
public string Url { get; set; }
public string Descriptor { get; set; }
}
private static readonly string FullWidth = "100vw";
private static readonly Regex SizeParser = CreateRegex();
private readonly IDocument _document;
private static Regex CreateRegex()
{
string pattern = "(\\([^)]+\\))?\\s*(.+)";
try {
return new Regex(pattern, RegexOptions.ECMAScript | RegexOptions.CultureInvariant);
} catch {
return new Regex(pattern, RegexOptions.ECMAScript);
}
}
public SourceSet(IDocument document)
{
_document = document;
}
private static IEnumerable<ImageCandidate> ParseSourceSet(string srcset)
{
string[] sources = srcset.Trim().SplitSpaces();
for (int i = 0; i < sources.Length; i++) {
string url = sources[i];
string descriptor = null;
if (url.Length != 0) {
if (url[url.Length - 1] == ',') {
url = url.Remove(url.Length - 1);
descriptor = string.Empty;
} else {
int num;
i = (num = i + 1);
if (num < sources.Length) {
descriptor = sources[i];
int num2 = descriptor.IndexOf(',');
if (num2 != -1) {
sources[i] = descriptor.Substring(num2 + 1);
descriptor = descriptor.Substring(0, num2);
i--;
}
}
}
yield return new ImageCandidate {
Url = url,
Descriptor = descriptor
};
}
}
}
private static MediaSize ParseSize(string sourceSizeStr)
{
Match match = SizeParser.Match(sourceSizeStr);
MediaSize mediaSize = new MediaSize();
mediaSize.Media = ((match.Success && match.Groups[1].Success) ? match.Groups[1].Value : string.Empty);
mediaSize.Length = ((match.Success && match.Groups[2].Success) ? match.Groups[2].Value : string.Empty);
return mediaSize;
}
private double ParseDescriptor(string descriptor, string sizesattr = null)
{
string sourceSizes = sizesattr ?? FullWidth;
string text = descriptor.Trim();
double widthFromSourceSize = GetWidthFromSourceSize(sourceSizes);
double result = 1;
string[] array = text.Split(new char[1] {
' '
});
for (int num = array.Length - 1; num >= 0; num--) {
string text2 = array[num];
char c = (text2.Length > 0) ? text2[text2.Length - 1] : ' ';
if ((c == 'h' || c == 'w') && text2.Length > 2 && text2[text2.Length] == 'v')
result = (double)text2.Substring(0, text2.Length - 2).ToInteger(0) / widthFromSourceSize;
else if (c == 'x' && text2.Length > 0) {
result = text2.Substring(0, text2.Length - 1).ToDouble(1);
}
}
return result;
}
private double GetWidthFromLength(string length)
{
Length result = default(Length);
Length.TryParse(length, out result);
return 0;
}
private double GetWidthFromSourceSize(string sourceSizes)
{
string[] array = sourceSizes.Trim().Split(new char[1] {
','
});
foreach (string sourceSizeStr in array) {
MediaSize mediaSize = ParseSize(sourceSizeStr);
string length = mediaSize.Length;
string media = mediaSize.Media;
if (!string.IsNullOrEmpty(length) && (string.IsNullOrEmpty(media) || _document.DefaultView.MatchMedia(media).IsMatched))
return GetWidthFromLength(length);
}
return GetWidthFromLength(FullWidth);
}
public IEnumerable<string> GetCandidates(string srcset, string sizes)
{
if (!string.IsNullOrEmpty(srcset)) {
foreach (ImageCandidate item in ParseSourceSet(srcset)) {
yield return item.Url;
}
}
}
}
}