diff --git a/PortablePorts/NReadability/MetaExtractor.cs b/PortablePorts/NReadability/MetaExtractor.cs
new file mode 100644
index 0000000..3632226
--- /dev/null
+++ b/PortablePorts/NReadability/MetaExtractor.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+
+namespace ReadSharp.Ports.NReadability
+{
+ public class MetaExtractor
+ {
+ ///
+ /// Gets or sets a value indicating whether [has value].
+ ///
+ ///
+ /// true if [has value]; otherwise, false.
+ ///
+ public bool HasValue { get; set; }
+
+ ///
+ /// Gets or sets the tags.
+ ///
+ ///
+ /// The tags.
+ ///
+ public IEnumerable Tags { get; private set; }
+
+
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The document.
+ public MetaExtractor(XDocument document)
+ {
+ var documentRoot = document.Root;
+
+ if (documentRoot == null || documentRoot.Name == null || !"html".Equals(documentRoot.Name.LocalName, StringComparison.OrdinalIgnoreCase))
+ {
+ HasValue = false;
+ return;
+ }
+
+ var headElement = documentRoot.GetChildrenByTagName("head").FirstOrDefault();
+
+ if (headElement == null)
+ {
+ HasValue = false;
+ return;
+ }
+
+ IEnumerable meta = headElement.GetChildrenByTagName("meta");
+ IEnumerable link = headElement.GetChildrenByTagName("link");
+
+ Tags = meta != null ? meta.Concat(link) : link;
+ HasValue = Tags != null && Tags.Count() > 0;
+ }
+
+
+ ///
+ /// Gets the meta description.
+ ///
+ ///
+ public string GetMetaDescription()
+ {
+ return SearchCandidates(new Dictionary()
+ {
+ { "property|og:description", "content" },
+ { "name|description", "content" }
+ });
+ }
+
+
+ ///
+ /// Gets the meta image.
+ ///
+ ///
+ public string GetMetaImage()
+ {
+ return SearchCandidates(new Dictionary()
+ {
+ { "property|og:image", "content" },
+ { "rel|apple-touch-icon", "href" },
+ { "rel|apple-touch-icon-precomposed", "href"},
+ { "name|msapplication-square310x310logo", "content" },
+ { "name|msapplication-square150x150logo", "content" },
+ { "name|msapplication-square70x70logo", "content" },
+ { "name|msapplication-TileImage", "content" },
+ { "rel|image_src", "href" }
+ });
+ }
+
+
+ ///
+ /// Gets the meta favicon.
+ ///
+ ///
+ public string GetMetaFavicon()
+ {
+ return SearchCandidates(new Dictionary()
+ {
+ { "rel|icon", "href" },
+ { "rel|shortcut icon", "href" }
+ });
+ }
+
+
+ ///
+ /// Searches the candidates.
+ ///
+ /// The candidates.
+ ///
+ private string SearchCandidates(Dictionary candidates)
+ {
+ string result = null;
+
+ foreach (var candidate in candidates)
+ {
+ string[] type = candidate.Key.Split('|');
+
+ XElement element = Tags
+ .Where(item => String.Equals(item.GetAttributeValue(type[0], null), type[1], StringComparison.OrdinalIgnoreCase))
+ .FirstOrDefault();
+
+ if (element != null)
+ {
+ result = element.GetAttributeValue(candidate.Value, "");
+ }
+
+ if (result != null && result.Length > 1)
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/PortablePorts/NReadability/NReadability.csproj b/PortablePorts/NReadability/NReadability.csproj
index 026ac77..155b3d1 100644
--- a/PortablePorts/NReadability/NReadability.csproj
+++ b/PortablePorts/NReadability/NReadability.csproj
@@ -49,6 +49,7 @@
+
diff --git a/PortablePorts/NReadability/NReadabilityTranscoder.cs b/PortablePorts/NReadability/NReadabilityTranscoder.cs
index 1328dd9..a04a70d 100644
--- a/PortablePorts/NReadability/NReadabilityTranscoder.cs
+++ b/PortablePorts/NReadability/NReadabilityTranscoder.cs
@@ -159,6 +159,7 @@ namespace ReadSharp.Ports.NReadability
private Func _imageSourceTranformer;
private Func _anchorHrefTransformer;
+ private Func _metaTransformer;
#endregion
@@ -249,11 +250,38 @@ namespace ReadSharp.Ports.NReadability
bool titleExtracted = !string.IsNullOrEmpty(extractedTitle);
+ MetaExtractor metaExtractor = new MetaExtractor(transcodedXmlDocument);
+
+ string description = null;
+ Uri image = null;
+ Uri favicon = null;
+
+ if (metaExtractor.HasValue)
+ {
+ description = metaExtractor.GetMetaDescription();
+ string imageString = metaExtractor.GetMetaImage();
+ string faviconString = metaExtractor.GetMetaFavicon();
+
+ if (imageString != null)
+ {
+ imageString = ResolveElementUrl(imageString, transcodingInput.Url);
+ Uri.TryCreate(imageString, UriKind.Absolute, out image);
+ }
+ if (faviconString != null)
+ {
+ faviconString = ResolveElementUrl(faviconString, transcodingInput.Url);
+ Uri.TryCreate(faviconString, UriKind.Absolute, out favicon);
+ }
+ }
+
return
new TranscodingResult(contentExtracted, titleExtracted)
{
ExtractedContent = transcodedContent,
ExtractedTitle = extractedTitle,
+ ExtractedDescription = description,
+ ExtractedFavicon = favicon,
+ ExtractedImage = image,
NextPageUrl = nextPageUrl,
Images = images
};
@@ -1835,6 +1863,13 @@ namespace ReadSharp.Ports.NReadability
set { _anchorHrefTransformer = value; }
}
+
+ public Func MetaTranformer
+ {
+ get { return _metaTransformer; }
+ set { _metaTransformer = value; }
+ }
+
#endregion
}
}
diff --git a/PortablePorts/NReadability/TranscodingResult.cs b/PortablePorts/NReadability/TranscodingResult.cs
index 49c07d9..a6bfff6 100644
--- a/PortablePorts/NReadability/TranscodingResult.cs
+++ b/PortablePorts/NReadability/TranscodingResult.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -21,6 +22,12 @@ namespace ReadSharp.Ports.NReadability
public string NextPageUrl { get; set; }
+ public string ExtractedDescription { get; set; }
+
+ public Uri ExtractedImage { get; set; }
+
+ public Uri ExtractedFavicon { get; set; }
+
public XDocument RawDocument { get; set; }
public IEnumerable Images { get; set; }
diff --git a/ReadSharp/Models/Article.cs b/ReadSharp/Models/Article.cs
index 5a7ba7e..5bd788d 100644
--- a/ReadSharp/Models/Article.cs
+++ b/ReadSharp/Models/Article.cs
@@ -8,6 +8,22 @@ namespace ReadSharp
///
public class Article
{
+ ///
+ /// Gets or sets the title.
+ ///
+ ///
+ /// The title.
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// Gets or sets the description.
+ ///
+ ///
+ /// The description.
+ ///
+ public string Description { get; set; }
+
///
/// Gets or sets the content.
///
@@ -16,6 +32,22 @@ namespace ReadSharp
///
public string Content { get; set; }
+ ///
+ /// Gets or sets the front image.
+ ///
+ ///
+ /// The front image.
+ ///
+ public Uri FrontImage { get; set; }
+
+ ///
+ /// Gets or sets the favicon.
+ ///
+ ///
+ /// The favicon.
+ ///
+ public Uri Favicon { get; set; }
+
///
/// Gets or sets the images.
///
@@ -24,14 +56,6 @@ namespace ReadSharp
///
public List Images { get; set; }
- ///
- /// Gets or sets the title.
- ///
- ///
- /// The title.
- ///
- public string Title { get; set; }
-
///
/// Gets or sets the next page URL.
///
diff --git a/ReadSharp/Reader.cs b/ReadSharp/Reader.cs
index 806cca4..8eadc50 100644
--- a/ReadSharp/Reader.cs
+++ b/ReadSharp/Reader.cs
@@ -68,7 +68,7 @@ namespace ReadSharp
///
/// An URI to extract the content from.
/// if set to true [only body is returned].
- /// if set to true [no headline (h1) is included].
+ /// if set to true [no headline (h1) is included in generated HTML].
///
/// An article with extracted content and meta information.
///
@@ -124,9 +124,12 @@ namespace ReadSharp
// create article
return new Article()
{
- Content = transcodingResult.ExtractedContent,
- Images = images,
Title = transcodingResult.ExtractedTitle,
+ Description = transcodingResult.ExtractedDescription,
+ Content = transcodingResult.ExtractedContent,
+ FrontImage = transcodingResult.ExtractedImage,
+ Images = images,
+ Favicon = transcodingResult.ExtractedFavicon,
NextPage = transcodingResult.NextPageUrl != null ? new Uri(transcodingResult.NextPageUrl, UriKind.Absolute) : null
};
}