converted SgmlReader & NReadability to PCL; start reader project
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
using NReadability;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// PocketReader
|
||||
/// </summary>
|
||||
public partial class PocketReader
|
||||
{
|
||||
/// <summary>
|
||||
/// REST client used for HTML retrieval
|
||||
/// </summary>
|
||||
protected readonly HttpClient _restClient;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PocketReader"/> class.
|
||||
/// </summary>
|
||||
public PocketReader()
|
||||
{
|
||||
// initialize REST client
|
||||
_restClient = new HttpClient(new HttpClientHandler()
|
||||
{
|
||||
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
|
||||
});
|
||||
|
||||
_restClient.DefaultRequestHeaders.Add("Accept", "text/html");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<string> Read(Uri uri)
|
||||
{
|
||||
NReadabilityTranscoder transcoder = new NReadabilityTranscoder();
|
||||
bool success;
|
||||
|
||||
string htmlResponse = await Request(uri);
|
||||
|
||||
string transcodedContent = transcoder.Transcode(htmlResponse, out success);
|
||||
|
||||
// //new TranscodingInput(
|
||||
// //transcoder.Transcode(
|
||||
// //string transcodedContent =
|
||||
// // transcoder.Transcode("https://github.com/marek-stoj/NReadability", out success);
|
||||
|
||||
|
||||
return transcodedContent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a typed resource
|
||||
/// </summary>
|
||||
protected async Task<string> Request(Uri uri)
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||
|
||||
// make async request
|
||||
HttpResponseMessage response = await _restClient.SendAsync(request);
|
||||
|
||||
// validate HTTP response
|
||||
ValidateResponse(response);
|
||||
|
||||
// read response
|
||||
var responseString = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return responseString;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Validates the response.
|
||||
/// </summary>
|
||||
/// <param name="response">The response.</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="PocketException">
|
||||
/// Error retrieving response
|
||||
/// </exception>
|
||||
protected void ValidateResponse(HttpResponseMessage response)
|
||||
{
|
||||
// no error found
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string exceptionString = String.Format("Request error: {0} ({1})", response.ReasonPhrase, (int)response.StatusCode);
|
||||
|
||||
throw new PocketException(exceptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{DB574D27-C040-453A-A459-4D6DCCBF2E2E}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PocketSharp.Reader</RootNamespace>
|
||||
<AssemblyName>PocketSharp.Reader</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Profile96</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="PocketReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Threading.Tasks">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Threading.Tasks.Extensions">
|
||||
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.6\lib\portable-net40+sl4+wp7+win8\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO">
|
||||
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.IO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Extensions">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Primitives">
|
||||
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime">
|
||||
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks">
|
||||
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PocketSharp\PocketSharp.csproj">
|
||||
<Project>{817200c3-a327-4e35-9b5f-63a51c088577}</Project>
|
||||
<Name>PocketSharp</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PortablePorts\NReadability\NReadability.csproj">
|
||||
<Project>{14c3ee6a-54a4-4a37-8b56-d52a3802f1c2}</Project>
|
||||
<Name>NReadability</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
|
||||
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PocketSharp.Reader")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PocketSharp.Reader")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Bcl" version="1.1.3" targetFramework="portable-net45+sl40+wp71+win" />
|
||||
<package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="portable-net45+sl40+wp71+win" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.10" targetFramework="portable-net45+sl40+wp71+win" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.15" targetFramework="portable-net403+sl40+wp71+win" />
|
||||
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="portable-net403+sl40+wp71+win" />
|
||||
</packages>
|
||||
@@ -72,9 +72,14 @@
|
||||
<Compile Include="ModifyTests.cs" />
|
||||
<Compile Include="GetTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReadTests.cs" />
|
||||
<Compile Include="TestsBase.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PocketSharp.Reader\PocketSharp.Reader.csproj">
|
||||
<Project>{db574d27-c040-453a-a459-4d6dccbf2e2e}</Project>
|
||||
<Name>PocketSharp.Reader</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PocketSharp\PocketSharp.csproj">
|
||||
<Project>{817200c3-a327-4e35-9b5f-63a51c088577}</Project>
|
||||
<Name>PocketSharp</Name>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
using PocketSharp.Models;
|
||||
|
||||
namespace PocketSharp.Tests
|
||||
{
|
||||
public class ReadTests : TestsBase
|
||||
{
|
||||
public ReadTests() : base() { }
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task TemporaryReadTest()
|
||||
{
|
||||
PocketReader reader = new PocketReader();
|
||||
|
||||
await reader.Read(new Uri("https://github.com/ceee/PocketSharp"));
|
||||
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{19DD45
|
||||
.nuget\NuGet.targets = .nuget\NuGet.targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NReadability", "PortablePorts\NReadability\NReadability.csproj", "{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SgmlReader", "PortablePorts\SgmlReader\SgmlReader.csproj", "{9112414C-E2D1-43BA-A298-A89F77D94332}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PortablePorts", "PortablePorts", "{82F79DE3-76D7-4FCB-AA7E-16BA7E363E0D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketSharp.Reader", "PocketSharp.Reader\PocketSharp.Reader.csproj", "{DB574D27-C040-453A-A459-4D6DCCBF2E2E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -82,6 +90,30 @@ Global
|
||||
{CA3C491B-A8CA-426C-A0BB-E91636767467}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA3C491B-A8CA-426C-A0BB-E91636767467}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{CA3C491B-A8CA-426C-A0BB-E91636767467}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{DB574D27-C040-453A-A459-4D6DCCBF2E2E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -90,5 +122,7 @@ Global
|
||||
{775569C2-987F-4AC4-8BA5-A315A21ED1B7} = {AFD4E3F1-B23C-4924-BA5B-D917FBADB8FA}
|
||||
{656345D2-AF4C-4F88-9C9F-EBF54D7691DB} = {AFD4E3F1-B23C-4924-BA5B-D917FBADB8FA}
|
||||
{47721A56-2128-4C5A-8B92-995FFC353304} = {AFD4E3F1-B23C-4924-BA5B-D917FBADB8FA}
|
||||
{9112414C-E2D1-43BA-A298-A89F77D94332} = {82F79DE3-76D7-4FCB-AA7E-16BA7E363E0D}
|
||||
{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2} = {82F79DE3-76D7-4FCB-AA7E-16BA7E363E0D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public class AttributeTransformationInput
|
||||
{
|
||||
public string AttributeValue { get; set; }
|
||||
|
||||
public XElement Element { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace NReadability
|
||||
{
|
||||
public class AttributeTransformationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Result of the transformation.
|
||||
/// </summary>
|
||||
public string TransformedValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the attribute that will be used to store the original value. Can be null.
|
||||
/// </summary>
|
||||
public string OriginalValueAttributeName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
internal class ChildNodesTraverser
|
||||
{
|
||||
private readonly Action<XNode> _childNodeVisitor;
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
public ChildNodesTraverser(Action<XNode> childNodeVisitor)
|
||||
{
|
||||
if (childNodeVisitor == null)
|
||||
{
|
||||
throw new ArgumentNullException("childNodeVisitor");
|
||||
}
|
||||
|
||||
_childNodeVisitor = childNodeVisitor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
public void Traverse(XNode node)
|
||||
{
|
||||
if (!(node is XContainer))
|
||||
{
|
||||
throw new ArgumentException("The node must be an XContainer in order to traverse its children.");
|
||||
}
|
||||
|
||||
var childNode = ((XContainer)node).FirstNode;
|
||||
|
||||
while (childNode != null)
|
||||
{
|
||||
var nextChildNode = childNode.NextNode;
|
||||
|
||||
_childNodeVisitor(childNode);
|
||||
|
||||
childNode = nextChildNode;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public static class Consts
|
||||
{
|
||||
private static readonly string _nReadabilityFullName;
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
static Consts()
|
||||
{
|
||||
_nReadabilityFullName = string.Format("NReadability {0}", Assembly.GetExecutingAssembly().FullName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public static string NReadabilityFullName
|
||||
{
|
||||
get { return _nReadabilityFullName; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public static class DomExtensions
|
||||
{
|
||||
#region XDocument extensions
|
||||
|
||||
public static XElement GetBody(this XDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException("document");
|
||||
}
|
||||
|
||||
var documentRoot = document.Root;
|
||||
|
||||
if (documentRoot == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return documentRoot.GetElementsByTagName("body").FirstOrDefault();
|
||||
}
|
||||
|
||||
public static string GetTitle(this XDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException("document");
|
||||
}
|
||||
|
||||
var documentRoot = document.Root;
|
||||
|
||||
if (documentRoot == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var headElement = documentRoot.GetElementsByTagName("head").FirstOrDefault();
|
||||
|
||||
if (headElement == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var titleElement = headElement.GetChildrenByTagName("title").FirstOrDefault();
|
||||
|
||||
if (titleElement == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return (titleElement.Value ?? "").Trim();
|
||||
}
|
||||
|
||||
public static XElement GetElementById(this XDocument document, string id)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException("document");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
return
|
||||
(from element in document.Descendants()
|
||||
let idAttribute = element.Attribute("id")
|
||||
where idAttribute != null && idAttribute.Value == id
|
||||
select element).SingleOrDefault();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XElement extensions
|
||||
|
||||
public static string GetId(this XElement element)
|
||||
{
|
||||
return element.GetAttributeValue("id", "");
|
||||
}
|
||||
|
||||
public static void SetId(this XElement element, string id)
|
||||
{
|
||||
element.SetAttributeValue("id", id);
|
||||
}
|
||||
|
||||
public static string GetClass(this XElement element)
|
||||
{
|
||||
return element.GetAttributeValue("class", "");
|
||||
}
|
||||
|
||||
public static void SetClass(this XElement element, string @class)
|
||||
{
|
||||
element.SetAttributeValue("class", @class);
|
||||
}
|
||||
|
||||
public static string GetStyle(this XElement element)
|
||||
{
|
||||
return element.GetAttributeValue("style", "");
|
||||
}
|
||||
|
||||
public static void SetStyle(this XElement element, string style)
|
||||
{
|
||||
element.SetAttributeValue("style", style);
|
||||
}
|
||||
|
||||
public static string GetAttributeValue(this XElement element, string attributeName, string defaultValue)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw new ArgumentNullException("element");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(attributeName))
|
||||
{
|
||||
throw new ArgumentNullException("attributeName");
|
||||
}
|
||||
|
||||
var attribute = element.Attribute(attributeName);
|
||||
|
||||
return attribute != null
|
||||
? (attribute.Value ?? defaultValue)
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
public static void SetAttributeValue(this XElement element, string attributeName, string value)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw new ArgumentNullException("element");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(attributeName))
|
||||
{
|
||||
throw new ArgumentNullException("attributeName");
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
var attribute = element.Attribute(attributeName);
|
||||
|
||||
if (attribute != null)
|
||||
{
|
||||
attribute.Remove();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
element.SetAttributeValue(attributeName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAttributesString(this XElement element, string separator)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw new ArgumentNullException("element");
|
||||
}
|
||||
|
||||
if (separator == null)
|
||||
{
|
||||
throw new ArgumentNullException("separator");
|
||||
}
|
||||
|
||||
var resultSb = new StringBuilder();
|
||||
bool isFirst = true;
|
||||
|
||||
element.Attributes().Aggregate(
|
||||
resultSb,
|
||||
(sb, attribute) =>
|
||||
{
|
||||
string attributeValue = attribute.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(attributeValue))
|
||||
{
|
||||
return sb;
|
||||
}
|
||||
|
||||
if (!isFirst)
|
||||
{
|
||||
resultSb.Append(separator);
|
||||
}
|
||||
|
||||
isFirst = false;
|
||||
|
||||
sb.Append(attribute.Value);
|
||||
|
||||
return sb;
|
||||
});
|
||||
|
||||
return resultSb.ToString();
|
||||
}
|
||||
|
||||
public static string GetInnerHtml(this XContainer container)
|
||||
{
|
||||
if (container == null)
|
||||
{
|
||||
throw new ArgumentNullException("container");
|
||||
}
|
||||
|
||||
var resultSb = new StringBuilder();
|
||||
|
||||
foreach (var childNode in container.Nodes())
|
||||
{
|
||||
resultSb.Append(childNode.ToString(SaveOptions.DisableFormatting));
|
||||
}
|
||||
|
||||
return resultSb.ToString();
|
||||
}
|
||||
|
||||
public static void SetInnerHtml(this XElement element, string html)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw new ArgumentNullException("element");
|
||||
}
|
||||
|
||||
if (html == null)
|
||||
{
|
||||
throw new ArgumentNullException("html");
|
||||
}
|
||||
|
||||
element.RemoveAll();
|
||||
|
||||
var tmpElement = new SgmlDomBuilder().BuildDocument(html);
|
||||
|
||||
if (tmpElement.Root == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var node in tmpElement.Root.Nodes())
|
||||
{
|
||||
element.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XContainer extensions
|
||||
|
||||
public static IEnumerable<XElement> GetElementsByTagName(this XContainer container, string tagName)
|
||||
{
|
||||
if (container == null)
|
||||
{
|
||||
throw new ArgumentNullException("container");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tagName))
|
||||
{
|
||||
throw new ArgumentNullException("tagName");
|
||||
}
|
||||
|
||||
return container.Descendants()
|
||||
.Where(e => tagName.Equals(e.Name.LocalName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public static IEnumerable<XElement> GetChildrenByTagName(this XContainer container, string tagName)
|
||||
{
|
||||
if (container == null)
|
||||
{
|
||||
throw new ArgumentNullException("container");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tagName))
|
||||
{
|
||||
throw new ArgumentNullException("tagName");
|
||||
}
|
||||
|
||||
return container.Elements()
|
||||
.Where(e => e.Name != null && tagName.Equals(e.Name.LocalName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public class DomSerializationParams
|
||||
{
|
||||
#region Factory methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of DomSerializationParams with parameters set to their defaults.
|
||||
/// </summary>
|
||||
public static DomSerializationParams CreateDefault()
|
||||
{
|
||||
return new DomSerializationParams();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the output will be formatted.
|
||||
/// </summary>
|
||||
public bool PrettyPrint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether DOCTYPE will be included at the beginning of the output.
|
||||
/// </summary>
|
||||
public bool DontIncludeContentTypeMetaElement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether mobile-specific elements (such as eg. meta HandheldFriendly) will be added/replaced in the output.
|
||||
/// </summary>
|
||||
public bool DontIncludeMobileSpecificMetaElements { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a meta tag with a content-type specification will be added/replaced in the output.
|
||||
/// </summary>
|
||||
public bool DontIncludeDocTypeMetaElement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a meta tag with a generator specification will be added/replaced in the output.
|
||||
/// </summary>
|
||||
public bool DontIncludeGeneratorMetaElement { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public class ElementsTraverser
|
||||
{
|
||||
private readonly Action<XElement> _elementVisitor;
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
public ElementsTraverser(Action<XElement> elementVisitor)
|
||||
{
|
||||
if (elementVisitor == null)
|
||||
{
|
||||
throw new ArgumentNullException("elementVisitor");
|
||||
}
|
||||
|
||||
_elementVisitor = elementVisitor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
public void Traverse(XElement element)
|
||||
{
|
||||
_elementVisitor(element);
|
||||
|
||||
var childNode = element.FirstNode;
|
||||
|
||||
while (childNode != null)
|
||||
{
|
||||
var nextChildNode = childNode.NextNode;
|
||||
|
||||
if (childNode is XElement)
|
||||
{
|
||||
Traverse((XElement)childNode);
|
||||
}
|
||||
|
||||
childNode = nextChildNode;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
internal class EncodedStringWriter : StringWriter
|
||||
{
|
||||
private static readonly Encoding _DefaultEncoding = Encoding.UTF8;
|
||||
|
||||
private readonly Encoding _encoding;
|
||||
|
||||
#region Constructor(s)
|
||||
|
||||
public EncodedStringWriter(StringBuilder sb, Encoding encoding)
|
||||
: base(sb)
|
||||
{
|
||||
if (encoding == null)
|
||||
{
|
||||
throw new ArgumentNullException("encoding");
|
||||
}
|
||||
|
||||
_encoding = encoding;
|
||||
}
|
||||
|
||||
public EncodedStringWriter(StringBuilder sb)
|
||||
: this(sb, _DefaultEncoding)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
public override Encoding Encoding
|
||||
{
|
||||
get { return _encoding; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the only one element in the sequence or default(T) if either the sequence doesn't contain any elements or it contains more than one element.
|
||||
/// </summary>
|
||||
public static T SingleOrNone<T>(this IEnumerable<T> enumerable)
|
||||
where T : class
|
||||
{
|
||||
// ReSharper disable PossibleMultipleEnumeration
|
||||
|
||||
if (enumerable == null)
|
||||
{
|
||||
throw new ArgumentNullException("enumerable");
|
||||
}
|
||||
|
||||
T firstElement = enumerable.FirstOrDefault();
|
||||
|
||||
if (firstElement == null)
|
||||
{
|
||||
// no elements
|
||||
return null;
|
||||
}
|
||||
|
||||
T secondElement = enumerable.Skip(1).FirstOrDefault();
|
||||
|
||||
if (secondElement != null)
|
||||
{
|
||||
// more than one element
|
||||
return null;
|
||||
}
|
||||
|
||||
return firstElement;
|
||||
|
||||
// ReSharper restore PossibleMultipleEnumeration
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines how the extracted article will be styled.
|
||||
/// </summary>
|
||||
public enum ReadingStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// Newspaper style.
|
||||
/// </summary>
|
||||
Newspaper,
|
||||
|
||||
/// <summary>
|
||||
/// Novel style.
|
||||
/// </summary>
|
||||
Novel,
|
||||
|
||||
/// <summary>
|
||||
/// Ebook style.
|
||||
/// </summary>
|
||||
Ebook,
|
||||
|
||||
/// <summary>
|
||||
/// Terminal style.
|
||||
/// </summary>
|
||||
Terminal,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how wide the margin of the extracted article will be.
|
||||
/// </summary>
|
||||
public enum ReadingMargin
|
||||
{
|
||||
/// <summary>
|
||||
/// Extra-narrow margin.
|
||||
/// </summary>
|
||||
XNarrow,
|
||||
|
||||
/// <summary>
|
||||
/// Narrow margin.
|
||||
/// </summary>
|
||||
Narrow,
|
||||
|
||||
/// <summary>
|
||||
/// Medium margin.
|
||||
/// </summary>
|
||||
Medium,
|
||||
|
||||
/// <summary>
|
||||
/// Wide margin.
|
||||
/// </summary>
|
||||
Wide,
|
||||
|
||||
/// <summary>
|
||||
/// Extra-wide margin.
|
||||
/// </summary>
|
||||
XWide,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how large the font of the extracted article will be.
|
||||
/// </summary>
|
||||
public enum ReadingSize
|
||||
{
|
||||
/// <summary>
|
||||
/// Extra-small font.
|
||||
/// </summary>
|
||||
XSmall,
|
||||
|
||||
/// <summary>
|
||||
/// Small font.
|
||||
/// </summary>
|
||||
Small,
|
||||
|
||||
/// <summary>
|
||||
/// Medium font.
|
||||
/// </summary>
|
||||
Medium,
|
||||
|
||||
/// <summary>
|
||||
/// Large font.
|
||||
/// </summary>
|
||||
Large,
|
||||
|
||||
/// <summary>
|
||||
/// Extra-large font.
|
||||
/// </summary>
|
||||
XLarge,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public static class HtmlUtils
|
||||
{
|
||||
public static string RemoveScriptTags(string htmlContent)
|
||||
{
|
||||
if (htmlContent == null)
|
||||
{
|
||||
throw new ArgumentNullException("htmlContent");
|
||||
}
|
||||
|
||||
if (htmlContent.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int indexOfScriptTagStart = htmlContent.IndexOf("<script", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (indexOfScriptTagStart == -1)
|
||||
{
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
int indexOfScriptTagEnd = htmlContent.IndexOf("</script>", indexOfScriptTagStart, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (indexOfScriptTagEnd == -1)
|
||||
{
|
||||
return htmlContent.Substring(0, indexOfScriptTagStart);
|
||||
}
|
||||
|
||||
string strippedHtmlContent =
|
||||
htmlContent.Substring(0, indexOfScriptTagStart) +
|
||||
htmlContent.Substring(indexOfScriptTagEnd + "</script>".Length);
|
||||
|
||||
return RemoveScriptTags(strippedHtmlContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception that is thrown when an internal error occurrs in the application.
|
||||
/// Internal error in the application means that there is a bug in the application.
|
||||
/// </summary>
|
||||
public class InternalErrorException : Exception
|
||||
{
|
||||
#region Constructor(s)
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the InternalErrorException class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
|
||||
public InternalErrorException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the InternalErrorException class with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public InternalErrorException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the InternalErrorException class.
|
||||
/// </summary>
|
||||
public InternalErrorException()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{14C3EE6A-54A4-4A37-8B56-D52A3802F1C2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NReadability</RootNamespace>
|
||||
<AssemblyName>NReadability</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Profile96</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
<Content Include="Resources\readability.css" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AttributeTransformationInput.cs" />
|
||||
<Compile Include="AttributeTransformationResult.cs" />
|
||||
<Compile Include="ChildNodesTraverser.cs" />
|
||||
<Compile Include="Consts.cs" />
|
||||
<Compile Include="DomExtensions.cs" />
|
||||
<Compile Include="DomSerializationParams.cs" />
|
||||
<Compile Include="ElementsTraverser.cs" />
|
||||
<Compile Include="EncodedStringWriter.cs" />
|
||||
<Compile Include="EnumerableExtensions.cs" />
|
||||
<Compile Include="Enums.cs" />
|
||||
<Compile Include="HtmlUtils.cs" />
|
||||
<Compile Include="InternalErrorException.cs" />
|
||||
<Compile Include="NReadabilityTranscoder.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SgmlDomBuilder.cs" />
|
||||
<Compile Include="SgmlDomSerializer.cs" />
|
||||
<Compile Include="TranscodingInput.cs" />
|
||||
<Compile Include="TranscodingResult.cs" />
|
||||
<Compile Include="UtilityExtensions.cs" />
|
||||
<Compile Include="WebTranscodingInput.cs" />
|
||||
<Compile Include="WebTranscodingResult.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SgmlReader\SgmlReader.csproj">
|
||||
<Project>{9112414c-e2d1-43ba-a298-a89f77d94332}</Project>
|
||||
<Name>SgmlReader</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("NReadabilityPCL")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("NReadabilityPCL")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,82 @@
|
||||
/* Document */
|
||||
body {font-size: 100%;}
|
||||
#readability-logo,#arc90-logo,.footer-twitterLink,#readTools a,a.rdbTK-powered span{background-color:transparent!important;background-image:url(http://lab.arc90.com/experiments/readability/images/sprite-readability.png)!important;background-repeat:no-repeat!important;}
|
||||
#readOverlay {display:block;position:absolute;top:0;left:0;width:100%;}
|
||||
#readInner {line-height:1.4em;max-width:800px;margin:1em auto;}
|
||||
#readInner a {color:#039;text-decoration:none;}
|
||||
#readInner a:hover {text-decoration:underline;}
|
||||
#readInner img {float:left;clear:both;margin: 0 12px 12px 0;}
|
||||
#readInner h1 {display:block;width:100%;border-bottom:1px solid #333;font-size:1.2em;padding-bottom:.5em;margin-top:0;margin-bottom:.75em;}
|
||||
#readInner sup{line-height:.8em;}
|
||||
#readInner .page-separator{clear:both;display:block;font-size:.85em;filter:alpha(opacity=20);opacity:.20;text-align:center;}
|
||||
.style-apertura #readInner h1 {border-bottom-color:#ededed;}
|
||||
#readInner blockquote {margin-left:3em;margin-right:3em;}
|
||||
#readability-inner * {margin-bottom:16px;border:none;background:none;}
|
||||
/* Footer */
|
||||
#readFooter {display:block;border-top:1px solid #333;text-align:center;clear:both;overflow:hidden;}
|
||||
.style-apertura #readFooter {border-top-color:#ededed;}
|
||||
#rdb-footer-left {display:inline;float:left;margin-top:15px;width:285px;background-position:0 -36px;}
|
||||
.rdbTypekit #rdb-footer-left {width:475px;}
|
||||
#rdb-footer-left a,#rdb-footer-left a:link {float:left;}
|
||||
#readability-logo {display:inline;background-position:0 -36px;height:29px;width:189px;text-indent:-9000px;}
|
||||
#arc90-logo {display:inline;background-position:right -36px;height:29px;width:96px;text-indent:-9000px;}
|
||||
#readability-url {display:none;}
|
||||
.style-apertura #readability-logo {background-position:0 -67px;}
|
||||
.style-apertura #arc90-logo {background-position:right -67px;}
|
||||
#rdb-footer-right {display:inline;float:right;text-align:right;font-size:.75em;margin-top:18px;}
|
||||
#rdb-footer-right a {display:inline-block;float:left;overflow:visible;line-height:16px;vertical-align:baseline;}
|
||||
.footer-twitterLink {height:20px;margin-left:20px;padding:4px 0 0 28px;background-position:0 -123px;font-size:12px;}
|
||||
#rdb-footer-left .footer-twitterLink {display:none;margin-top:1px;padding-top:2px;}
|
||||
.rdbTypekit #rdb-footer-right .footer-twitterLink {display:none;}
|
||||
.rdbTypekit #rdb-footer-left .footer-twitterLink {display:inline-block!important;}
|
||||
a.rdbTK-powered,a.rdbTK-powered:link,a.rdbTK-powered:hover {font-size:16px;color:#858789!important;text-decoration:none!important;}
|
||||
a.rdbTK-powered span {display:inline-block;height:22px;margin-left:2px;padding:4px 0 0 26px;background-position:0 -146px!important;}
|
||||
.style-apertura #rdb-inverse,.style-athelas #rdb-athelas {display:block;}
|
||||
span.version {display:none;}
|
||||
/* Tools */
|
||||
#readTools {width:34px;height:150px;position:fixed;z-index:100;top:10px;left:10px;}
|
||||
#readTools a {overflow:hidden;margin-bottom:8px;display:block;opacity:.4;text-indent:-99999px;height:34px;width:34px;text-decoration:none;filter:alpha(opacity=40);}
|
||||
#reload-page {background-position:0 0;}
|
||||
#print-page {background-position:-36px 0;}
|
||||
#email-page {background-position:-72px 0;}
|
||||
#kindle-page {background-position:-108px 0;}
|
||||
#readTools a:hover {opacity:1;filter:alpha(opacity=100);}
|
||||
/* -- USER-CONFIGURABLE STYLING -- */
|
||||
/* Size */
|
||||
.size-x-small {font-size:.75em;}
|
||||
.size-small {font-size:.938em;}
|
||||
.size-medium {font-size:1.125em;}
|
||||
.size-large {font-size:1.375em;}
|
||||
.size-x-large {font-size:1.75em;}
|
||||
/* Style */
|
||||
.style-newspaper {font-family:"Times New Roman", Times, serif;background:#fbfbfb;color:#080000;}
|
||||
.style-newspaper h1 {text-transform:capitalize;font-family:Georgia, "Times New Roman", Times, serif;}
|
||||
.style-newspaper #readInner a {color:#0924e1;}
|
||||
.style-novel {font-family:"Palatino Linotype", "Book Antiqua", Palatino, serif;background:#f4eed9;color:#1d1916;}
|
||||
.style-novel #readInner a {color:#1856ba;}
|
||||
.style-ebook {font-family:Arial, Helvetica, sans-serif;background:#edebe8;color:#2c2d32;}
|
||||
.style-ebook #readInner a {color:#187dc9;}
|
||||
.style-ebook h1 {font-family:"Arial Black", Gadget, sans-serif;font-weight:400;}
|
||||
.style-terminal {font-family:"Lucida Console", Monaco, monospace;background:#1d4e2c;color:#c6ffc6;}
|
||||
.style-terminal #readInner a {color:#093;}
|
||||
/* Typekit */
|
||||
.style-apertura {font-family:"apertura-1", "apertura-2", sans-serif;background-color:#2d2828;color:#eae8e9;}
|
||||
.style-apertura #readInner a {color:#58b0ff;}
|
||||
.style-athelas {font-family:"athelas-1", "athelas-2", "Palatino Linotype", "Book Antiqua", Palatino, serif;background-color:#f7f7f7;color:#2b373d;}
|
||||
.style-athelas #readInner a {color:#1e83cb;}
|
||||
/* Margin */
|
||||
.margin-x-narrow {width:95%;}
|
||||
.margin-narrow {width:85%;}
|
||||
.margin-medium {width:75%;}
|
||||
.margin-wide {width:55%;}
|
||||
.margin-x-wide {width:35%;}
|
||||
/* -- USER-CONFIGURABLE STYLING -- */
|
||||
/* -- DEBUG -- */
|
||||
.bug-green {background:#bbf9b0;border:4px solid green;}
|
||||
.bug-red {background:red;}
|
||||
.bug-yellow {background:#ffff8e;}
|
||||
.bug-blue {background:#bfdfff;}
|
||||
/* -- EMAIL / KINDLE POP UP -- */
|
||||
#kindle-container, #email-container {position:fixed;top:60px;left:50%;width:500px;height:490px;border:solid 3px #666;background-color:#fff;z-index:100!important;overflow:hidden;margin:0 0 0 -240px;padding:0;}
|
||||
/* Override html styling attributes */
|
||||
table, tr, td { background-color: transparent !important; }
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Sgml;
|
||||
using System.IO;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
/// <summary>
|
||||
/// A class for constructing a DOM from HTML markup.
|
||||
/// </summary>
|
||||
public class SgmlDomBuilder
|
||||
{
|
||||
#region Public methods
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a DOM (System.Xml.Linq.XDocument) from HTML markup.
|
||||
/// </summary>
|
||||
/// <param name="htmlContent">HTML markup from which the DOM is to be constructed.</param>
|
||||
/// <returns>System.Linq.Xml.XDocument instance which is a DOM of the provided HTML markup.</returns>
|
||||
public XDocument BuildDocument(string htmlContent)
|
||||
{
|
||||
if (htmlContent == null)
|
||||
{
|
||||
throw new ArgumentNullException("htmlContent");
|
||||
}
|
||||
|
||||
if (htmlContent.Trim().Length == 0)
|
||||
{
|
||||
return new XDocument();
|
||||
}
|
||||
|
||||
// "trim end" htmlContent to ...</html>$ (codinghorror.com puts some scripts after the </html> - sic!)
|
||||
const string htmlEnd = "</html";
|
||||
int indexOfHtmlEnd = htmlContent.LastIndexOf(htmlEnd);
|
||||
|
||||
if (indexOfHtmlEnd != -1)
|
||||
{
|
||||
int indexOfHtmlEndBracket = htmlContent.IndexOf('>', indexOfHtmlEnd);
|
||||
|
||||
if (indexOfHtmlEndBracket != -1)
|
||||
{
|
||||
htmlContent = htmlContent.Substring(0, indexOfHtmlEndBracket + 1);
|
||||
}
|
||||
}
|
||||
|
||||
XDocument document;
|
||||
|
||||
try
|
||||
{
|
||||
document = LoadDocument(htmlContent);
|
||||
}
|
||||
catch (InvalidOperationException exc)
|
||||
{
|
||||
// sometimes SgmlReader doesn't handle <script> tags well and XDocument.Load() throws,
|
||||
// so we can retry with the html content with <script> tags stripped off
|
||||
|
||||
if (!exc.Message.Contains("EndOfFile"))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
htmlContent = HtmlUtils.RemoveScriptTags(htmlContent);
|
||||
|
||||
document = LoadDocument(htmlContent);
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
private static XDocument LoadDocument(string htmlContent)
|
||||
{
|
||||
using (var sgmlReader = new SgmlReader())
|
||||
{
|
||||
sgmlReader.CaseFolding = CaseFolding.ToLower;
|
||||
sgmlReader.DocType = "HTML";
|
||||
sgmlReader.WhitespaceHandling = WhitespaceHandling.None;
|
||||
|
||||
using (var sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(htmlContent))))
|
||||
{
|
||||
sgmlReader.InputStream = sr;
|
||||
|
||||
var document = XDocument.Load(sgmlReader);
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
/// <summary>
|
||||
/// A class for serializing a DOM to string.
|
||||
/// </summary>
|
||||
public class SgmlDomSerializer
|
||||
{
|
||||
#region Public methods
|
||||
|
||||
/// <summary>
|
||||
/// Serializes given DOM (System.Xml.Linq.XDocument object) to a string.
|
||||
/// </summary>
|
||||
/// <param name="document">System.Xml.Linq.XDocument instance containing the DOM to be serialized.</param>
|
||||
/// <param name="domSerializationParams">Contains parameters that modify the behaviour of the output serialization.</param>
|
||||
/// <returns>Serialized representation of the DOM.</returns>
|
||||
public string SerializeDocument(XDocument document, DomSerializationParams domSerializationParams)
|
||||
{
|
||||
if (!domSerializationParams.DontIncludeContentTypeMetaElement
|
||||
|| !domSerializationParams.DontIncludeMobileSpecificMetaElements
|
||||
|| !domSerializationParams.DontIncludeGeneratorMetaElement)
|
||||
{
|
||||
var documentRoot = document.Root;
|
||||
|
||||
if (documentRoot == null)
|
||||
{
|
||||
throw new ArgumentException("The document must have a root.");
|
||||
}
|
||||
|
||||
if (documentRoot.Name == null || !"html".Equals(documentRoot.Name.LocalName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new ArgumentException("The document's root must be an html element.");
|
||||
}
|
||||
|
||||
// add <head> element if not present
|
||||
var headElement = documentRoot.GetChildrenByTagName("head").FirstOrDefault();
|
||||
|
||||
if (headElement == null)
|
||||
{
|
||||
headElement = new XElement("head");
|
||||
documentRoot.AddFirst(headElement);
|
||||
}
|
||||
|
||||
ProcessMetaElements(headElement, domSerializationParams);
|
||||
}
|
||||
|
||||
string result = document.ToString(domSerializationParams.PrettyPrint ? SaveOptions.None : SaveOptions.DisableFormatting);
|
||||
|
||||
if (!domSerializationParams.DontIncludeDocTypeMetaElement)
|
||||
{
|
||||
result = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\r\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n" + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes given DOM (System.Xml.Linq.XDocument object) to a string.
|
||||
/// </summary>
|
||||
/// <param name="document">System.Xml.Linq.XDocument instance containing the DOM to be serialized.</param>
|
||||
/// <returns>Serialized representation of the DOM.</returns>
|
||||
public string SerializeDocument(XDocument document)
|
||||
{
|
||||
return SerializeDocument(document, DomSerializationParams.CreateDefault());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private helper methods
|
||||
|
||||
private static void ProcessMetaElements(XElement headElement, DomSerializationParams domSerializationParams)
|
||||
{
|
||||
ProcessMetaContentTypeElement(headElement, domSerializationParams);
|
||||
ProcessMobileSpecificMetaElements(headElement, domSerializationParams);
|
||||
ProcessMetaGeneratorElement(headElement, domSerializationParams);
|
||||
}
|
||||
|
||||
private static void ProcessMetaContentTypeElement(XElement headElement, DomSerializationParams domSerializationParams)
|
||||
{
|
||||
if (!domSerializationParams.DontIncludeContentTypeMetaElement)
|
||||
{
|
||||
XElement metaContentTypeElement =
|
||||
(from metaElement in headElement.GetChildrenByTagName("meta")
|
||||
where "content-type".Equals(metaElement.GetAttributeValue("http-equiv", ""), StringComparison.OrdinalIgnoreCase)
|
||||
select metaElement).FirstOrDefault();
|
||||
|
||||
// remove meta 'http-equiv' element if present
|
||||
if (metaContentTypeElement != null)
|
||||
{
|
||||
metaContentTypeElement.Remove();
|
||||
}
|
||||
|
||||
// add <meta name="http-equiv" ... /> element
|
||||
metaContentTypeElement =
|
||||
new XElement(
|
||||
XName.Get("meta", headElement.Name != null ? (headElement.Name.NamespaceName ?? "") : ""),
|
||||
new XAttribute("http-equiv", "Content-Type"),
|
||||
new XAttribute("content", "text/html; charset=utf-8"));
|
||||
|
||||
headElement.AddFirst(metaContentTypeElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessMobileSpecificMetaElements(XElement headElement, DomSerializationParams domSerializationParams)
|
||||
{
|
||||
XElement metaViewportElement =
|
||||
(from metaElement in headElement.GetChildrenByTagName("meta")
|
||||
where "viewport".Equals(metaElement.GetAttributeValue("name", ""), StringComparison.OrdinalIgnoreCase)
|
||||
select metaElement).FirstOrDefault();
|
||||
|
||||
// remove meta 'viewport' element if present
|
||||
if (metaViewportElement != null)
|
||||
{
|
||||
metaViewportElement.Remove();
|
||||
}
|
||||
|
||||
XElement metaHandheldFriendlyElement =
|
||||
(from metaElement in headElement.GetChildrenByTagName("meta")
|
||||
where "HandheldFriendly".Equals(metaElement.GetAttributeValue("name", ""), StringComparison.OrdinalIgnoreCase)
|
||||
select metaElement).FirstOrDefault();
|
||||
|
||||
// remove meta 'HandheldFriendly' element if present
|
||||
if (metaHandheldFriendlyElement != null)
|
||||
{
|
||||
metaHandheldFriendlyElement.Remove();
|
||||
}
|
||||
|
||||
if (!domSerializationParams.DontIncludeMobileSpecificMetaElements)
|
||||
{
|
||||
// add <meta name="HandheldFriendly" ... /> element
|
||||
metaHandheldFriendlyElement = new XElement(
|
||||
XName.Get("meta", headElement.Name != null ? (headElement.Name.NamespaceName ?? "") : ""),
|
||||
new XAttribute("name", "HandheldFriendly"),
|
||||
new XAttribute("content", "true"));
|
||||
|
||||
headElement.AddFirst(metaHandheldFriendlyElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessMetaGeneratorElement(XElement headElement, DomSerializationParams domSerializationParams)
|
||||
{
|
||||
if (!domSerializationParams.DontIncludeGeneratorMetaElement)
|
||||
{
|
||||
XElement metaGeneratorElement =
|
||||
(from metaElement in headElement.GetChildrenByTagName("meta")
|
||||
where "Generator".Equals(metaElement.GetAttributeValue("name", ""), StringComparison.OrdinalIgnoreCase)
|
||||
select metaElement).FirstOrDefault();
|
||||
|
||||
// remove meta 'generator' element if present
|
||||
if (metaGeneratorElement != null)
|
||||
{
|
||||
metaGeneratorElement.Remove();
|
||||
}
|
||||
|
||||
// add <meta name="Generator" ... /> element
|
||||
metaGeneratorElement = new XElement(
|
||||
XName.Get("meta", headElement.Name != null ? (headElement.Name.NamespaceName ?? "") : ""),
|
||||
new XAttribute("name", "Generator"),
|
||||
new XAttribute("content", Consts.NReadabilityFullName));
|
||||
|
||||
headElement.AddFirst(metaGeneratorElement);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public class TranscodingInput
|
||||
{
|
||||
private DomSerializationParams _domSerializationParams;
|
||||
|
||||
public TranscodingInput(string htmlContent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(htmlContent))
|
||||
{
|
||||
throw new ArgumentException("Argument can't be null nor empty.", "htmlContent");
|
||||
}
|
||||
|
||||
HtmlContent = htmlContent;
|
||||
}
|
||||
|
||||
public string HtmlContent { get; private set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public DomSerializationParams DomSerializationParams
|
||||
{
|
||||
get { return _domSerializationParams ?? (_domSerializationParams = DomSerializationParams.CreateDefault()); }
|
||||
set { _domSerializationParams = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace NReadability
|
||||
{
|
||||
public class TranscodingResult
|
||||
{
|
||||
public TranscodingResult(bool contentExtracted, bool titleExtracted)
|
||||
{
|
||||
ContentExtracted = contentExtracted;
|
||||
TitleExtracted = titleExtracted;
|
||||
}
|
||||
|
||||
public bool ContentExtracted { get; private set; }
|
||||
|
||||
public bool TitleExtracted { get; private set; }
|
||||
|
||||
public string ExtractedContent { get; set; }
|
||||
|
||||
public string ExtractedTitle { get; set; }
|
||||
|
||||
public string NextPageUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* NReadability
|
||||
* http://code.google.com/p/nreadability/
|
||||
*
|
||||
* Copyright 2010 Marek Stój
|
||||
* http://immortal.pl/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
internal static class UtilityExtensions
|
||||
{
|
||||
#region Public methods
|
||||
|
||||
public static bool IsCloseToZero(this float x)
|
||||
{
|
||||
return Math.Abs(x) < float.Epsilon;
|
||||
}
|
||||
|
||||
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
|
||||
{
|
||||
foreach (var element in enumerable)
|
||||
{
|
||||
action(element);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace NReadability
|
||||
{
|
||||
public class WebTranscodingInput
|
||||
{
|
||||
private DomSerializationParams _domSerializationParams;
|
||||
|
||||
public WebTranscodingInput(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
{
|
||||
throw new ArgumentException("Argument can't be null nor empty.", "url");
|
||||
}
|
||||
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public string Url { get; private set; }
|
||||
|
||||
public DomSerializationParams DomSerializationParams
|
||||
{
|
||||
get { return _domSerializationParams ?? (_domSerializationParams = DomSerializationParams.CreateDefault()); }
|
||||
set { _domSerializationParams = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace NReadability
|
||||
{
|
||||
public class WebTranscodingResult
|
||||
{
|
||||
public WebTranscodingResult(bool contentExtracted, bool titleExtracted)
|
||||
{
|
||||
ContentExtracted = contentExtracted;
|
||||
TitleExtracted = titleExtracted;
|
||||
}
|
||||
|
||||
public bool ContentExtracted { get; private set; }
|
||||
|
||||
public bool TitleExtracted { get; private set; }
|
||||
|
||||
public string ExtractedContent { get; set; }
|
||||
|
||||
public string ExtractedTitle { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SgmlReader")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SgmlReader")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{9112414C-E2D1-43BA-A298-A89F77D94332}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SgmlReader</RootNamespace>
|
||||
<AssemblyName>SgmlReader</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Profile96</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
<None Include="Html.dtd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SgmlParser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SgmlReader.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
Reference in New Issue
Block a user