Merge branch 'master' into master

This commit is contained in:
Opportunity
2019-10-01 21:31:02 +08:00
committed by GitHub
31 changed files with 1124 additions and 443 deletions

View File

@@ -1,11 +1,15 @@
version: 10.0.{build}
image: Visual Studio 2017
configuration: Release
environment:
COVERALLS_REPO_TOKEN:
secure: /SEtLgIE6ZrJaWBC1xFZIeESiwfwiXEk9N4pSJ53rFhqBZC2sXJg7ZxZ1DBhnZGu
install:
- ps: >-
cd src
dotnet tool install -g coveralls.net --version 1.0.0
nuget restore Markdig.sln
$env:MARKDIG_BUILD_NUMBER = ([int]$env:APPVEYOR_BUILD_NUMBER).ToString("000")
@@ -31,22 +35,35 @@ build:
project: src/Markdig.sln
verbosity: minimal
after_build:
- cmd: >-
dotnet run --project SpecFileGen/SpecFileGen.csproj -c Release
after_build: >
dotnet SpecFileGen/bin/Release/netcoreapp2.2/SpecFileGen.dll
dotnet test -v n Markdig.Tests
test_script:
- cmd: >-
dotnet test Markdig.Tests -c Release --no-build
dotnet test Markdig.Tests -c Debug
dotnet test Markdig.Tests -c Release -f netcoreapp2.1 /p:CollectCoverage=true /p:Include=\"[Markdig]*\" /p:CoverletOutputFormat=opencover /p:CoverletOutput=../../coverage.xml
after_test:
- ps: >-
if($env:APPVEYOR_REPO_BRANCH -eq "master") {
cd ..
if (Test-Path "./coverage.xml") {
csmacnz.Coveralls --opencover -i "./coverage.xml" --repoToken $env:COVERALLS_REPO_TOKEN --basePath "$env:APPVEYOR_BUILD_FOLDER" --useRelativePath --commitId $env:APPVEYOR_REPO_COMMIT --commitBranch $env:APPVEYOR_REPO_BRANCH --commitAuthor $env:APPVEYOR_REPO_COMMIT_AUTHOR --commitEmail $env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL --commitMessage $env:APPVEYOR_REPO_COMMIT_MESSAGE --jobId $env:APPVEYOR_BUILD_NUMBER --serviceName appveyor
}
cd src
}
before_package:
- cmd: >-
msbuild /t:pack /p:VersionSuffix="%MARKDIG_VERSION_SUFFIX%" /p:Configuration=Release Markdig/Markdig.csproj
msbuild /t:Clean Markdig/Markdig.csproj
msbuild /t:pack /p:VersionSuffix="%MARKDIG_VERSION_SUFFIX%" /p:Configuration=Release;SignAssembly=true Markdig/Markdig.csproj
msbuild /t:pack /p:VersionSuffix="%MARKDIG_VERSION_SUFFIX%" /p:Configuration=Release Markdig.Signed/Markdig.Signed.csproj
artifacts:
- path: src\Markdig\Bin\Release\*.nupkg
- path: src\**\*.nupkg
name: Markdig Nugets
deploy:

View File

@@ -1,9 +1,11 @@
# Changelog
## WIP
- Fix regression when escaping HTML characters ([(PR #340)](https://github.com/lunet-io/markdig/pull/340))
- Add `IHostProvider` for medialink customization (#337), support protocol-less url (#135) ([(PR #341)](https://github.com/lunet-io/markdig/pull/341))
## 0.17.1 (04 July 2019)
- Fix regression when escaping HTML characters ([(PR #340)](https://github.com/lunet-io/markdig/pull/340))
- Update Emoji Dictionary ([(PR #346)](https://github.com/lunet-io/markdig/pull/346))
## 0.17.0 (10 May 2019)
- Update to latest CommonMark specs 0.29 ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))
- Add `AutoLinkOptions` with `OpenInNewWindow`, `UseHttpsForWWWLinks` ([(PR #327)](https://github.com/lunet-io/markdig/pull/327))

View File

@@ -1,4 +1,4 @@
# Markdig [![Build status](https://ci.appveyor.com/api/projects/status/hk391x8jcskxt1u8?svg=true)](https://ci.appveyor.com/project/xoofx/markdig) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
# Markdig [![Build status](https://ci.appveyor.com/api/projects/status/hk391x8jcskxt1u8?svg=true)](https://ci.appveyor.com/project/xoofx/markdig) [![Coverage Status](https://coveralls.io/repos/github/lunet-io/markdig/badge.svg?branch=master)](https://coveralls.io/github/lunet-io/markdig?branch=master) [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
<img align="right" width="160px" height="160px" src="img/markdig.png">

View File

@@ -1,43 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.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')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6A19F040-BC7C-4283-873A-177B5324F1ED}</ProjectGuid>
<TargetFrameworks>net471</TargetFrameworks>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Markdig.Benchmarks</RootNamespace>
<AssemblyName>Markdig.Benchmarks</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<CopyNuGetImplementations>true</CopyNuGetImplementations>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<None Remove="spec.md" />
</ItemGroup>
<ItemGroup>
<Reference Include="CommonMarkNew, Version=0.1.0.0, Culture=neutral, PublicKeyToken=001ef8810438905d, processorArchitecture=MSIL">
<HintPath>lib\CommonMarkNew.dll</HintPath>
@@ -45,31 +14,12 @@
<Aliases>newcmark</Aliases>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Build" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
<Reference Include="MoonShine">
<HintPath>lib\MoonShine.dll</HintPath>
</Reference>
<Reference Include="MarkdownDeep">
<HintPath>lib\MarkdownDeep.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CommonMarkLib.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestMatchPerf.cs" />
<Compile Include="TestStringPerf.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="cmark.dll">
@@ -83,21 +33,16 @@
<Content Include="spec.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="app.config" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Reference Include="Markdig">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Markdig\Bin\$(Configuration)\net40\Markdig.dll</HintPath>
</Reference>
<PackageReference Include="BenchmarkDotNet" Version="0.10.6" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.10.6" />
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
<PackageReference Include="MarkdownSharp" Version="1.13.0.0" />
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="0.8.31-beta" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="1.0.41.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.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>
<ItemGroup>
<ProjectReference Include="..\Markdig\Markdig.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,36 +0,0 @@
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("Testamina.Markdig.Benchmarks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Testamina.Markdig.Benchmarks")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6a19f040-bc7c-4283-873a-177b5324f1ed")]
// 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")]

View File

@@ -1,8 +0,0 @@
{
"profiles": {
"CLASSIC": {
"executablePath": "Testamina.Markdig.Benchmarks.dll",
"workingDirectory": "..\\..\\artifacts\\bin\\Testamina.Markdig.Benchmarks\\Debug\\net45"
}
}
}

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>

View File

@@ -1,29 +0,0 @@
{
"runtimes": {
"win-x86": {},
"win-x64": {}
},
"frameworks": {
"net46": {
"compilationOptions": {
"define": [
"CLASSIC"
]
},
"frameworkAssemblies": {
"Microsoft.Build": "4.0.0.0",
"Microsoft.Build.Framework": "4.0.0.0",
"Microsoft.Build.Utilities.v4.0": "4.0.0.0",
"System.Management": "4.0.0.0"
}
}
},
"dependencies": {
"BenchmarkDotNet": "0.10.6",
"BenchmarkDotNet.Diagnostics.Windows": "0.10.6",
"CommonMark.NET": "0.15.1",
"MarkdownSharp": "1.13.0.0",
"Microsoft.Diagnostics.Runtime": "0.8.31-beta",
"Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.41.0"
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Markdig.Signed</PackageId>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Markdig\**\*.cs" Exclude="..\Markdig\obj\**;..\Markdig\bin\**">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>
<Import Project="..\Markdig\Markdig.targets" />
</Project>

View File

@@ -6,8 +6,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.6.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="NUnit" Version="3.11.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
</ItemGroup>

View File

@@ -8,6 +8,16 @@ namespace Markdig.Tests
{
public class MiscTests
{
[Test]
public void IsIssue356Corrected()
{
string input = @"https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97";
string expected = @"<p><a href=""https://foo.bar/path/%5C#m4mv5W0GYKZpGvfA.97"">https://foo.bar/path/\#m4mv5W0GYKZpGvfA.97</a></p>";
TestParser.TestSpec($"<{input}>", expected);
TestParser.TestSpec(input, expected, "autolinks|advanced");
}
[Test]
public void TestAltTextIsCorrectlyEscaped()
{

View File

@@ -1,4 +1,4 @@
// Generated: 2019-04-05 16:06:14
// Generated: 2019-08-01 13:57:17
// --------------------------------
// Generic Attributes
@@ -79,5 +79,28 @@ namespace Markdig.Tests.Specs.GenericAttributes
Console.WriteLine("Example 2\nSection Extensions / Generic Attributes\n");
TestParser.TestSpec("{#fenced-id .fenced-class}\n~~~\nThis is a fenced with attached attributes\n~~~ ", "<pre><code id=\"fenced-id\" class=\"fenced-class\">This is a fenced with attached attributes\n</code></pre>", "attributes|advanced");
}
// Attribute values can be one character long
[Test]
public void ExtensionsGenericAttributes_Example003()
{
// Example 3
// Section: Extensions / Generic Attributes
//
// The following Markdown:
// [Foo](url){data-x=1}
//
// [Foo](url){data-x='1'}
//
// [Foo](url){data-x=11}
//
// Should be rendered as:
// <p><a href="url" data-x="1">Foo</a></p>
// <p><a href="url" data-x="1">Foo</a></p>
// <p><a href="url" data-x="11">Foo</a></p>
Console.WriteLine("Example 3\nSection Extensions / Generic Attributes\n");
TestParser.TestSpec("[Foo](url){data-x=1}\n\n[Foo](url){data-x='1'}\n\n[Foo](url){data-x=11}", "<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"1\">Foo</a></p>\n<p><a href=\"url\" data-x=\"11\">Foo</a></p>", "attributes|advanced");
}
}
}

View File

@@ -47,3 +47,17 @@ This is a fenced with attached attributes
<pre><code id="fenced-id" class="fenced-class">This is a fenced with attached attributes
</code></pre>
````````````````````````````````
Attribute values can be one character long
```````````````````````````````` example
[Foo](url){data-x=1}
[Foo](url){data-x='1'}
[Foo](url){data-x=11}
.
<p><a href="url" data-x="1">Foo</a></p>
<p><a href="url" data-x="1">Foo</a></p>
<p><a href="url" data-x="11">Foo</a></p>
````````````````````````````````

View File

@@ -1,4 +1,4 @@
// Generated: 2019-04-05 16:06:14
// Generated: 2019-08-01 12:33:23
// --------------------------------
// Smarty Pants
@@ -140,13 +140,13 @@ namespace Markdig.Tests.Specs.SmartyPants
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// This is a 'text <<with' a another text>>
// This is 'a "text 'with" a another text'
//
// Should be rendered as:
// <p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>
// <p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>
Console.WriteLine("Example 8\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a 'text <<with' a another text>>", "<p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("This is 'a \"text 'with\" a another text'", "<p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
@@ -156,20 +156,36 @@ namespace Markdig.Tests.Specs.SmartyPants
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// This is a 'text <<with' a another text>>
//
// Should be rendered as:
// <p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>
Console.WriteLine("Example 9\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a 'text <<with' a another text>>", "<p>This is a &lsquo;text &lt;&lt;with&rsquo; a another text&gt;&gt;</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
public void ExtensionsSmartyPantsQuotes_Example010()
{
// Example 10
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// This is a <<text 'with>> a another text'
//
// Should be rendered as:
// <p>This is a &laquo;text 'with&raquo; a another text'</p>
Console.WriteLine("Example 9\nSection Extensions / SmartyPants Quotes\n");
Console.WriteLine("Example 10\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is a <<text 'with>> a another text'", "<p>This is a &laquo;text 'with&raquo; a another text'</p>", "pipetables+smartypants|advanced+smartypants");
}
// Quotes requires to have the same rules than emphasis `_` regarding left/right frankling rules:
[Test]
public void ExtensionsSmartyPantsQuotes_Example010()
public void ExtensionsSmartyPantsQuotes_Example011()
{
// Example 10
// Example 11
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
@@ -178,24 +194,8 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>It's not quotes'</p>
Console.WriteLine("Example 10\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("It's not quotes'", "<p>It's not quotes'</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
public void ExtensionsSmartyPantsQuotes_Example011()
{
// Example 11
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// They are ' not matching quotes '
//
// Should be rendered as:
// <p>They are ' not matching quotes '</p>
Console.WriteLine("Example 11\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("They are ' not matching quotes '", "<p>They are ' not matching quotes '</p>", "pipetables+smartypants|advanced+smartypants");
TestParser.TestSpec("It's not quotes'", "<p>It's not quotes'</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
@@ -205,20 +205,36 @@ namespace Markdig.Tests.Specs.SmartyPants
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// They are ' not matching quotes '
//
// Should be rendered as:
// <p>They are ' not matching quotes '</p>
Console.WriteLine("Example 12\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("They are ' not matching quotes '", "<p>They are ' not matching quotes '</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
public void ExtensionsSmartyPantsQuotes_Example013()
{
// Example 13
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// They are' not matching 'quotes
//
// Should be rendered as:
// <p>They are' not matching 'quotes</p>
Console.WriteLine("Example 12\nSection Extensions / SmartyPants Quotes\n");
Console.WriteLine("Example 13\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("They are' not matching 'quotes", "<p>They are' not matching 'quotes</p>", "pipetables+smartypants|advanced+smartypants");
}
// An emphasis starting inside left/right quotes will span over the right quote:
[Test]
public void ExtensionsSmartyPantsQuotes_Example013()
public void ExtensionsSmartyPantsQuotes_Example014()
{
// Example 13
// Example 14
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
@@ -227,9 +243,26 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>
Console.WriteLine("Example 13\nSection Extensions / SmartyPants Quotes\n");
Console.WriteLine("Example 14\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("This is \"a *text\" with an emphasis*", "<p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>", "pipetables+smartypants|advanced+smartypants");
}
// Multiple sets of quotes can be used
[Test]
public void ExtensionsSmartyPantsQuotes_Example015()
{
// Example 15
// Section: Extensions / SmartyPants Quotes
//
// The following Markdown:
// "aaa" "bbb" "ccc" "ddd"
//
// Should be rendered as:
// <p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>
Console.WriteLine("Example 15\nSection Extensions / SmartyPants Quotes\n");
TestParser.TestSpec("\"aaa\" \"bbb\" \"ccc\" \"ddd\"", "<p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>", "pipetables+smartypants|advanced+smartypants");
}
}
[TestFixture]
@@ -237,9 +270,9 @@ namespace Markdig.Tests.Specs.SmartyPants
{
// ## SmartyPants Separators
[Test]
public void ExtensionsSmartyPantsSeparators_Example014()
public void ExtensionsSmartyPantsSeparators_Example016()
{
// Example 14
// Example 16
// Section: Extensions / SmartyPants Separators
//
// The following Markdown:
@@ -248,14 +281,14 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &ndash; text</p>
Console.WriteLine("Example 14\nSection Extensions / SmartyPants Separators\n");
Console.WriteLine("Example 16\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a -- text", "<p>This is a &ndash; text</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
public void ExtensionsSmartyPantsSeparators_Example015()
public void ExtensionsSmartyPantsSeparators_Example017()
{
// Example 15
// Example 17
// Section: Extensions / SmartyPants Separators
//
// The following Markdown:
@@ -264,14 +297,14 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a &mdash; text</p>
Console.WriteLine("Example 15\nSection Extensions / SmartyPants Separators\n");
Console.WriteLine("Example 17\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a --- text", "<p>This is a &mdash; text</p>", "pipetables+smartypants|advanced+smartypants");
}
[Test]
public void ExtensionsSmartyPantsSeparators_Example016()
public void ExtensionsSmartyPantsSeparators_Example018()
{
// Example 16
// Example 18
// Section: Extensions / SmartyPants Separators
//
// The following Markdown:
@@ -280,15 +313,15 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>This is a en ellipsis&hellip;</p>
Console.WriteLine("Example 16\nSection Extensions / SmartyPants Separators\n");
Console.WriteLine("Example 18\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("This is a en ellipsis...", "<p>This is a en ellipsis&hellip;</p>", "pipetables+smartypants|advanced+smartypants");
}
// Check that a smartypants are not breaking pipetable parsing:
[Test]
public void ExtensionsSmartyPantsSeparators_Example017()
public void ExtensionsSmartyPantsSeparators_Example019()
{
// Example 17
// Example 19
// Section: Extensions / SmartyPants Separators
//
// The following Markdown:
@@ -312,15 +345,15 @@ namespace Markdig.Tests.Specs.SmartyPants
// </tbody>
// </table>
Console.WriteLine("Example 17\nSection Extensions / SmartyPants Separators\n");
Console.WriteLine("Example 19\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("a | b\n-- | --\n0 | 1", "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1</td>\n</tr>\n</tbody>\n</table>", "pipetables+smartypants|advanced+smartypants");
}
// Check quotes and dash:
[Test]
public void ExtensionsSmartyPantsSeparators_Example018()
public void ExtensionsSmartyPantsSeparators_Example020()
{
// Example 18
// Example 20
// Section: Extensions / SmartyPants Separators
//
// The following Markdown:
@@ -329,7 +362,7 @@ namespace Markdig.Tests.Specs.SmartyPants
// Should be rendered as:
// <p>A &ldquo;quote&rdquo; with a &mdash;</p>
Console.WriteLine("Example 18\nSection Extensions / SmartyPants Separators\n");
Console.WriteLine("Example 20\nSection Extensions / SmartyPants Separators\n");
TestParser.TestSpec("A \"quote\" with a ---", "<p>A &ldquo;quote&rdquo; with a &mdash;</p>", "pipetables+smartypants|advanced+smartypants");
}
}

View File

@@ -52,6 +52,12 @@ This is a "text 'with" a another text'
<p>This is a &ldquo;text 'with&rdquo; a another text'</p>
````````````````````````````````
```````````````````````````````` example
This is 'a "text 'with" a another text'
.
<p>This is &lsquo;a &ldquo;text 'with&rdquo; a another text&rsquo;</p>
````````````````````````````````
```````````````````````````````` example
This is a 'text <<with' a another text>>
.
@@ -91,6 +97,14 @@ This is "a *text" with an emphasis*
<p>This is &ldquo;a <em>text&rdquo; with an emphasis</em></p>
````````````````````````````````
Multiple sets of quotes can be used
```````````````````````````````` example
"aaa" "bbb" "ccc" "ddd"
.
<p>&ldquo;aaa&rdquo; &ldquo;bbb&rdquo; &ldquo;ccc&rdquo; &ldquo;ddd&rdquo;</p>
````````````````````````````````
## SmartyPants Separators
```````````````````````````````` example

View File

@@ -33,9 +33,9 @@ namespace Markdig.Tests
// If file creation times aren't preserved by git, add some leeway
// If specs have come from git, assume that they were regenerated since CI would fail otherwise
testTime = testTime.AddSeconds(2);
testTime = testTime.AddMinutes(3);
// This might not catch a changed spec every time, but should most of the time. Otherwise CI will catch it
// This might not catch a changed spec every time, but should at least sometimes. Otherwise CI will catch it
// This could also trigger, if a user has modified the spec file but reverted the change - can't think of a good workaround
Assert.Less(specTime, testTime,

View File

@@ -3,7 +3,7 @@
// See the license.txt file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Markdig.Helpers;
using Markdig.Parsers;
@@ -47,9 +47,9 @@ namespace Markdig.Extensions.Emoji
public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
// Previous char must be a space
if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero())
{
return false;
if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero())
{
return false;
}
// Try to match an emoji
@@ -75,8 +75,8 @@ namespace Markdig.Extensions.Emoji
slice.Start += match.Key.Length;
return true;
}
}
#region Emojis and Smileys
static EmojiParser()
{
@@ -961,6 +961,733 @@ namespace Markdig.Extensions.Emoji
{ ":custom_arrow_left_strong:", "⇐"},
{ ":custom_arrow_right_strong:", "⇒"},
{ ":custom_arrow_left_right_strong:", "⇔"},
{":rofl:","🤣"},
{":slightly_smiling_face:","🙂"},
{":upside_down_face:","🙃"},
{":star_struck:","🤩"},
{":zany_face:","🤪"},
{":money_mouth_face:","🤑"},
{":hugs:","🤗"},
{":hand_over_mouth:","🤭"},
{":shushing_face:","🤫"},
{":thinking:","🤔"},
{":zipper_mouth_face:","🤐"},
{":raised_eyebrow:","🤨"},
{":roll_eyes:","🙄"},
{":lying_face:","🤥"},
{":drooling_face:","🤤"},
{":face_with_thermometer:","🤒"},
{":face_with_head_bandage:","🤕"},
{":nauseated_face:","🤢"},
{":vomiting_face:","🤮"},
{":sneezing_face:","🤧"},
{":exploding_head:","🤯"},
{":cowboy_hat_face:","🤠"},
{":nerd_face:","🤓"},
{":monocle_face:","🧐"},
{":slightly_frowning_face:","🙁"},
{":frowning_face:","☹️"},
{":cursing_face:","🤬"},
{":skull_and_crossbones:","☠️"},
{":clown_face:","🤡"},
{":robot:","🤖"},
{":heavy_heart_exclamation:","❣️"},
{":orange_heart:","🧡"},
{":black_heart:","🖤"},
{":hole:","🕳️"},
{":eye_speech_bubble:","👁️‍🗨️"},
{":left_speech_bubble:","🗨️"},
{":right_anger_bubble:","🗯️"},
{":raised_back_of_hand:","🤚"},
{":raised_hand_with_fingers_splayed:","🖐️"},
{":vulcan_salute:","🖖"},
{":crossed_fingers:","🤞"},
{":love_you_gesture:","🤟"},
{":metal:","🤘"},
{":call_me_hand:","🤙"},
{":middle_finger:","🖕"},
{":fist_raised:","✊"},
{":fist_oncoming:","👊"},
{":fist_left:","🤛"},
{":fist_right:","🤜"},
{":palms_up_together:","🤲"},
{":handshake:","🤝"},
{":writing_hand:","✍️"},
{":selfie:","🤳"},
{":brain:","🧠"},
{":eye:","👁️"},
{":child:","🧒"},
{":adult:","🧑"},
{":blond_haired_person:","👱"},
{":bearded_person:","🧔"},
{":blond_haired_man:","👱‍♂️"},
{":blond_haired_woman:","👱‍♀️"},
{":older_adult:","🧓"},
{":frowning_person:","🙍"},
{":frowning_man:","🙍‍♂️"},
{":frowning_woman:","🙍‍♀️"},
{":pouting_face:","🙎"},
{":pouting_man:","🙎‍♂️"},
{":pouting_woman:","🙎‍♀️"},
{":no_good_man:","🙅‍♂️"},
{":no_good_woman:","🙅‍♀️"},
{":ok_person:","🙆"},
{":ok_man:","🙆‍♂️"},
{":tipping_hand_person:","💁"},
{":tipping_hand_man:","💁‍♂️"},
{":tipping_hand_woman:","💁‍♀️"},
{":raising_hand_man:","🙋‍♂️"},
{":raising_hand_woman:","🙋‍♀️"},
{":bowing_man:","🙇‍♂️"},
{":bowing_woman:","🙇‍♀️"},
{":facepalm:","🤦"},
{":man_facepalming:","🤦‍♂️"},
{":woman_facepalming:","🤦‍♀️"},
{":shrug:","🤷"},
{":man_shrugging:","🤷‍♂️"},
{":woman_shrugging:","🤷‍♀️"},
{":man_health_worker:","👨‍⚕️"},
{":woman_health_worker:","👩‍⚕️"},
{":man_student:","👨‍🎓"},
{":woman_student:","👩‍🎓"},
{":man_teacher:","👨‍🏫"},
{":woman_teacher:","👩‍🏫"},
{":man_judge:","👨‍⚖️"},
{":woman_judge:","👩‍⚖️"},
{":man_farmer:","👨‍🌾"},
{":woman_farmer:","👩‍🌾"},
{":man_cook:","👨‍🍳"},
{":woman_cook:","👩‍🍳"},
{":man_mechanic:","👨‍🔧"},
{":woman_mechanic:","👩‍🔧"},
{":man_factory_worker:","👨‍🏭"},
{":woman_factory_worker:","👩‍🏭"},
{":man_office_worker:","👨‍💼"},
{":woman_office_worker:","👩‍💼"},
{":man_scientist:","👨‍🔬"},
{":woman_scientist:","👩‍🔬"},
{":man_technologist:","👨‍💻"},
{":woman_technologist:","👩‍💻"},
{":man_singer:","👨‍🎤"},
{":woman_singer:","👩‍🎤"},
{":man_artist:","👨‍🎨"},
{":woman_artist:","👩‍🎨"},
{":man_pilot:","👨‍✈️"},
{":woman_pilot:","👩‍✈️"},
{":man_astronaut:","👨‍🚀"},
{":woman_astronaut:","👩‍🚀"},
{":man_firefighter:","👨‍🚒"},
{":woman_firefighter:","👩‍🚒"},
{":police_officer:","👮"},
{":policeman:","👮‍♂️"},
{":policewoman:","👮‍♀️"},
{":detective:","🕵️"},
{":male_detective:","🕵️‍♂️"},
{":female_detective:","🕵️‍♀️"},
{":guard:","💂"},
{":guardswoman:","💂‍♀️"},
{":construction_worker_man:","👷‍♂️"},
{":construction_worker_woman:","👷‍♀️"},
{":prince:","🤴"},
{":person_with_turban:","👳"},
{":woman_with_turban:","👳‍♀️"},
{":woman_with_headscarf:","🧕"},
{":man_in_tuxedo:","🤵"},
{":pregnant_woman:","🤰"},
{":breast_feeding:","🤱"},
{":mrs_claus:","🤶"},
{":mage:","🧙"},
{":mage_man:","🧙‍♂️"},
{":mage_woman:","🧙‍♀️"},
{":fairy:","🧚"},
{":fairy_man:","🧚‍♂️"},
{":fairy_woman:","🧚‍♀️"},
{":vampire:","🧛"},
{":vampire_man:","🧛‍♂️"},
{":vampire_woman:","🧛‍♀️"},
{":merperson:","🧜"},
{":merman:","🧜‍♂️"},
{":mermaid:","🧜‍♀️"},
{":elf:","🧝"},
{":elf_man:","🧝‍♂️"},
{":elf_woman:","🧝‍♀️"},
{":genie:","🧞"},
{":genie_man:","🧞‍♂️"},
{":genie_woman:","🧞‍♀️"},
{":zombie:","🧟"},
{":zombie_man:","🧟‍♂️"},
{":zombie_woman:","🧟‍♀️"},
{":massage_man:","💆‍♂️"},
{":massage_woman:","💆‍♀️"},
{":haircut_man:","💇‍♂️"},
{":haircut_woman:","💇‍♀️"},
{":walking_man:","🚶‍♂️"},
{":walking_woman:","🚶‍♀️"},
{":running_man:","🏃‍♂️"},
{":running_woman:","🏃‍♀️"},
{":woman_dancing:","💃"},
{":man_dancing:","🕺"},
{":business_suit_levitating:","🕴️"},
{":dancing_men:","👯‍♂️"},
{":dancing_women:","👯‍♀️"},
{":sauna_person:","🧖"},
{":sauna_man:","🧖‍♂️"},
{":sauna_woman:","🧖‍♀️"},
{":climbing:","🧗"},
{":climbing_man:","🧗‍♂️"},
{":climbing_woman:","🧗‍♀️"},
{":person_fencing:","🤺"},
{":skier:","⛷️"},
{":golfing:","🏌️"},
{":golfing_man:","🏌️‍♂️"},
{":golfing_woman:","🏌️‍♀️"},
{":surfing_man:","🏄‍♂️"},
{":surfing_woman:","🏄‍♀️"},
{":rowing_man:","🚣‍♂️"},
{":rowing_woman:","🚣‍♀️"},
{":swimming_man:","🏊‍♂️"},
{":swimming_woman:","🏊‍♀️"},
{":bouncing_ball_person:","⛹️"},
{":bouncing_ball_man:","⛹️‍♂️"},
{":bouncing_ball_woman:","⛹️‍♀️"},
{":weight_lifting:","🏋️"},
{":weight_lifting_man:","🏋️‍♂️"},
{":weight_lifting_woman:","🏋️‍♀️"},
{":biking_man:","🚴‍♂️"},
{":biking_woman:","🚴‍♀️"},
{":mountain_biking_man:","🚵‍♂️"},
{":mountain_biking_woman:","🚵‍♀️"},
{":cartwheeling:","🤸"},
{":man_cartwheeling:","🤸‍♂️"},
{":woman_cartwheeling:","🤸‍♀️"},
{":wrestling:","🤼"},
{":men_wrestling:","🤼‍♂️"},
{":women_wrestling:","🤼‍♀️"},
{":water_polo:","🤽"},
{":man_playing_water_polo:","🤽‍♂️"},
{":woman_playing_water_polo:","🤽‍♀️"},
{":handball_person:","🤾"},
{":man_playing_handball:","🤾‍♂️"},
{":woman_playing_handball:","🤾‍♀️"},
{":juggling_person:","🤹"},
{":man_juggling:","🤹‍♂️"},
{":woman_juggling:","🤹‍♀️"},
{":lotus_position:","🧘"},
{":lotus_position_man:","🧘‍♂️"},
{":lotus_position_woman:","🧘‍♀️"},
{":sleeping_bed:","🛌"},
{":people_holding_hands:","🧑‍🤝‍🧑"},
{":couplekiss_man_woman:","👩‍❤️‍💋‍👨"},
{":couplekiss_man_man:","👨‍❤️‍💋‍👨"},
{":couplekiss_woman_woman:","👩‍❤️‍💋‍👩"},
{":couple_with_heart_woman_man:","👩‍❤️‍👨"},
{":couple_with_heart_man_man:","👨‍❤️‍👨"},
{":couple_with_heart_woman_woman:","👩‍❤️‍👩"},
{":family_man_woman_boy:","👨‍👩‍👦"},
{":family_man_woman_girl:","👨‍👩‍👧"},
{":family_man_woman_girl_boy:","👨‍👩‍👧‍👦"},
{":family_man_woman_boy_boy:","👨‍👩‍👦‍👦"},
{":family_man_woman_girl_girl:","👨‍👩‍👧‍👧"},
{":family_man_man_boy:","👨‍👨‍👦"},
{":family_man_man_girl:","👨‍👨‍👧"},
{":family_man_man_girl_boy:","👨‍👨‍👧‍👦"},
{":family_man_man_boy_boy:","👨‍👨‍👦‍👦"},
{":family_man_man_girl_girl:","👨‍👨‍👧‍👧"},
{":family_woman_woman_boy:","👩‍👩‍👦"},
{":family_woman_woman_girl:","👩‍👩‍👧"},
{":family_woman_woman_girl_boy:","👩‍👩‍👧‍👦"},
{":family_woman_woman_boy_boy:","👩‍👩‍👦‍👦"},
{":family_woman_woman_girl_girl:","👩‍👩‍👧‍👧"},
{":family_man_boy:","👨‍👦"},
{":family_man_boy_boy:","👨‍👦‍👦"},
{":family_man_girl:","👨‍👧"},
{":family_man_girl_boy:","👨‍👧‍👦"},
{":family_man_girl_girl:","👨‍👧‍👧"},
{":family_woman_boy:","👩‍👦"},
{":family_woman_boy_boy:","👩‍👦‍👦"},
{":family_woman_girl:","👩‍👧"},
{":family_woman_girl_boy:","👩‍👧‍👦"},
{":family_woman_girl_girl:","👩‍👧‍👧"},
{":speaking_head:","🗣️"},
{":gorilla:","🦍"},
{":fox_face:","🦊"},
{":lion:","🦁"},
{":unicorn:","🦄"},
{":zebra:","🦓"},
{":deer:","🦌"},
{":giraffe:","🦒"},
{":rhinoceros:","🦏"},
{":chipmunk:","🐿️"},
{":hedgehog:","🦔"},
{":bat:","🦇"},
{":turkey:","🦃"},
{":dove:","🕊️"},
{":eagle:","🦅"},
{":duck:","🦆"},
{":owl:","🦉"},
{":lizard:","🦎"},
{":sauropod:","🦕"},
{":t-rex:","🦖"},
{":shark:","🦈"},
{":butterfly:","🦋"},
{":cricket:","🦗"},
{":spider:","🕷️"},
{":spider_web:","🕸️"},
{":scorpion:","🦂"},
{":rosette:","🏵️"},
{":wilted_flower:","🥀"},
{":shamrock:","☘️"},
{":kiwi_fruit:","🥝"},
{":coconut:","🥥"},
{":avocado:","🥑"},
{":potato:","🥔"},
{":carrot:","🥕"},
{":hot_pepper:","🌶️"},
{":cucumber:","🥒"},
{":broccoli:","🥦"},
{":peanuts:","🥜"},
{":croissant:","🥐"},
{":baguette_bread:","🥖"},
{":pretzel:","🥨"},
{":pancakes:","🥞"},
{":cheese:","🧀"},
{":cut_of_meat:","🥩"},
{":bacon:","🥓"},
{":hotdog:","🌭"},
{":sandwich:","🥪"},
{":taco:","🌮"},
{":burrito:","🌯"},
{":stuffed_flatbread:","🥙"},
{":fried_egg:","🍳"},
{":shallow_pan_of_food:","🥘"},
{":bowl_with_spoon:","🥣"},
{":green_salad:","🥗"},
{":popcorn:","🍿"},
{":canned_food:","🥫"},
{":dumpling:","🥟"},
{":fortune_cookie:","🥠"},
{":takeout_box:","🥡"},
{":crab:","🦀"},
{":shrimp:","🦐"},
{":squid:","🦑"},
{":pie:","🥧"},
{":milk_glass:","🥛"},
{":champagne:","🍾"},
{":clinking_glasses:","🥂"},
{":tumbler_glass:","🥃"},
{":cup_with_straw:","🥤"},
{":chopsticks:","🥢"},
{":plate_with_cutlery:","🍽️"},
{":spoon:","🥄"},
{":amphora:","🏺"},
{":world_map:","🗺️"},
{":mountain_snow:","🏔️"},
{":mountain:","⛰️"},
{":camping:","🏕️"},
{":beach_umbrella:","🏖️"},
{":desert:","🏜️"},
{":desert_island:","🏝️"},
{":national_park:","🏞️"},
{":stadium:","🏟️"},
{":classical_building:","🏛️"},
{":building_construction:","🏗️"},
{":houses:","🏘️"},
{":derelict_house:","🏚️"},
{":mosque:","🕌"},
{":synagogue:","🕍"},
{":shinto_shrine:","⛩️"},
{":kaaba:","🕋"},
{":cityscape:","🏙️"},
{":racing_car:","🏎️"},
{":motorcycle:","🏍️"},
{":motor_scooter:","🛵"},
{":kick_scooter:","🛴"},
{":motorway:","🛣️"},
{":railway_track:","🛤️"},
{":oil_drum:","🛢️"},
{":stop_sign:","🛑"},
{":canoe:","🛶"},
{":passenger_ship:","🛳️"},
{":ferry:","⛴️"},
{":motor_boat:","🛥️"},
{":small_airplane:","🛩️"},
{":flight_departure:","🛫"},
{":flight_arrival:","🛬"},
{":artificial_satellite:","🛰️"},
{":flying_saucer:","🛸"},
{":bellhop_bell:","🛎️"},
{":stopwatch:","⏱️"},
{":timer_clock:","⏲️"},
{":mantelpiece_clock:","🕰️"},
{":thermometer:","🌡️"},
{":cloud_with_lightning_and_rain:","⛈️"},
{":sun_behind_small_cloud:","🌤️"},
{":sun_behind_large_cloud:","🌥️"},
{":sun_behind_rain_cloud:","🌦️"},
{":cloud_with_rain:","🌧️"},
{":cloud_with_snow:","🌨️"},
{":cloud_with_lightning:","🌩️"},
{":tornado:","🌪️"},
{":fog:","🌫️"},
{":wind_face:","🌬️"},
{":open_umbrella:","☂️"},
{":parasol_on_ground:","⛱️"},
{":snowman_with_snow:","☃️"},
{":comet:","☄️"},
{":reminder_ribbon:","🎗️"},
{":tickets:","🎟️"},
{":medal_military:","🎖️"},
{":medal_sports:","🏅"},
{":1st_place_medal:","🥇"},
{":2nd_place_medal:","🥈"},
{":3rd_place_medal:","🥉"},
{":volleyball:","🏐"},
{":cricket_game:","🏏"},
{":field_hockey:","🏑"},
{":ice_hockey:","🏒"},
{":ping_pong:","🏓"},
{":badminton:","🏸"},
{":boxing_glove:","🥊"},
{":martial_arts_uniform:","🥋"},
{":goal_net:","🥅"},
{":ice_skate:","⛸️"},
{":sled:","🛷"},
{":curling_stone:","🥌"},
{":joystick:","🕹️"},
{":chess_pawn:","♟️"},
{":framed_picture:","🖼️"},
{":dark_sunglasses:","🕶️"},
{":scarf:","🧣"},
{":gloves:","🧤"},
{":coat:","🧥"},
{":socks:","🧦"},
{":shopping:","🛍️"},
{":billed_cap:","🧢"},
{":rescue_worker_helmet:","⛑️"},
{":prayer_beads:","📿"},
{":studio_microphone:","🎙️"},
{":level_slider:","🎚️"},
{":control_knobs:","🎛️"},
{":drum:","🥁"},
{":desktop_computer:","🖥️"},
{":printer:","🖨️"},
{":keyboard:","⌨️"},
{":computer_mouse:","🖱️"},
{":trackball:","🖲️"},
{":film_strip:","🎞️"},
{":film_projector:","📽️"},
{":camera_flash:","📸"},
{":candle:","🕯️"},
{":newspaper_roll:","🗞️"},
{":label:","🏷️"},
{":ballot_box:","🗳️"},
{":fountain_pen:","🖋️"},
{":pen:","🖊️"},
{":paintbrush:","🖌️"},
{":crayon:","🖍️"},
{":card_index_dividers:","🗂️"},
{":spiral_notepad:","🗒️"},
{":spiral_calendar:","🗓️"},
{":paperclips:","🖇️"},
{":card_file_box:","🗃️"},
{":file_cabinet:","🗄️"},
{":wastebasket:","🗑️"},
{":old_key:","🗝️"},
{":pick:","⛏️"},
{":hammer_and_pick:","⚒️"},
{":hammer_and_wrench:","🛠️"},
{":dagger:","🗡️"},
{":crossed_swords:","⚔️"},
{":bow_and_arrow:","🏹"},
{":shield:","🛡️"},
{":gear:","⚙️"},
{":clamp:","🗜️"},
{":balance_scale:","⚖️"},
{":chains:","⛓️"},
{":alembic:","⚗️"},
{":bed:","🛏️"},
{":couch_and_lamp:","🛋️"},
{":shopping_cart:","🛒"},
{":coffin:","⚰️"},
{":funeral_urn:","⚱️"},
{":radioactive:","☢️"},
{":biohazard:","☣️"},
{":place_of_worship:","🛐"},
{":atom_symbol:","⚛️"},
{":om:","🕉️"},
{":star_of_david:","✡️"},
{":wheel_of_dharma:","☸️"},
{":yin_yang:","☯️"},
{":latin_cross:","✝️"},
{":orthodox_cross:","☦️"},
{":star_and_crescent:","☪️"},
{":peace_symbol:","☮️"},
{":menorah:","🕎"},
{":next_track_button:","⏭️"},
{":play_or_pause_button:","⏯️"},
{":previous_track_button:","⏮️"},
{":pause_button:","⏸️"},
{":stop_button:","⏹️"},
{":record_button:","⏺️"},
{":eject_button:","⏏️"},
{":female_sign:","♀️"},
{":male_sign:","♂️"},
{":medical_symbol:","⚕️"},
{":infinity:","♾️"},
{":fleur_de_lis:","⚜️"},
{":asterisk:","*️⃣"},
{":black_flag:","🏴"},
{":white_flag:","🏳️"},
{":rainbow_flag:","🏳️‍🌈"},
{":pirate_flag:","🏴‍☠️"},
{":ascension_island:","🇦🇨"},
{":andorra:","🇦🇩"},
{":united_arab_emirates:","🇦🇪"},
{":afghanistan:","🇦🇫"},
{":antigua_barbuda:","🇦🇬"},
{":anguilla:","🇦🇮"},
{":albania:","🇦🇱"},
{":armenia:","🇦🇲"},
{":angola:","🇦🇴"},
{":antarctica:","🇦🇶"},
{":argentina:","🇦🇷"},
{":american_samoa:","🇦🇸"},
{":austria:","🇦🇹"},
{":australia:","🇦🇺"},
{":aruba:","🇦🇼"},
{":aland_islands:","🇦🇽"},
{":azerbaijan:","🇦🇿"},
{":bosnia_herzegovina:","🇧🇦"},
{":barbados:","🇧🇧"},
{":bangladesh:","🇧🇩"},
{":belgium:","🇧🇪"},
{":burkina_faso:","🇧🇫"},
{":bulgaria:","🇧🇬"},
{":bahrain:","🇧🇭"},
{":burundi:","🇧🇮"},
{":benin:","🇧🇯"},
{":st_barthelemy:","🇧🇱"},
{":bermuda:","🇧🇲"},
{":brunei:","🇧🇳"},
{":bolivia:","🇧🇴"},
{":caribbean_netherlands:","🇧🇶"},
{":brazil:","🇧🇷"},
{":bahamas:","🇧🇸"},
{":bhutan:","🇧🇹"},
{":bouvet_island:","🇧🇻"},
{":botswana:","🇧🇼"},
{":belarus:","🇧🇾"},
{":belize:","🇧🇿"},
{":canada:","🇨🇦"},
{":cocos_islands:","🇨🇨"},
{":congo_kinshasa:","🇨🇩"},
{":central_african_republic:","🇨🇫"},
{":congo_brazzaville:","🇨🇬"},
{":switzerland:","🇨🇭"},
{":cote_divoire:","🇨🇮"},
{":cook_islands:","🇨🇰"},
{":chile:","🇨🇱"},
{":cameroon:","🇨🇲"},
{":colombia:","🇨🇴"},
{":clipperton_island:","🇨🇵"},
{":costa_rica:","🇨🇷"},
{":cuba:","🇨🇺"},
{":cape_verde:","🇨🇻"},
{":curacao:","🇨🇼"},
{":christmas_island:","🇨🇽"},
{":cyprus:","🇨🇾"},
{":czech_republic:","🇨🇿"},
{":diego_garcia:","🇩🇬"},
{":djibouti:","🇩🇯"},
{":denmark:","🇩🇰"},
{":dominica:","🇩🇲"},
{":dominican_republic:","🇩🇴"},
{":algeria:","🇩🇿"},
{":ceuta_melilla:","🇪🇦"},
{":ecuador:","🇪🇨"},
{":estonia:","🇪🇪"},
{":egypt:","🇪🇬"},
{":western_sahara:","🇪🇭"},
{":eritrea:","🇪🇷"},
{":ethiopia:","🇪🇹"},
{":eu:","🇪🇺"},
{":finland:","🇫🇮"},
{":fiji:","🇫🇯"},
{":falkland_islands:","🇫🇰"},
{":micronesia:","🇫🇲"},
{":faroe_islands:","🇫🇴"},
{":gabon:","🇬🇦"},
{":grenada:","🇬🇩"},
{":georgia:","🇬🇪"},
{":french_guiana:","🇬🇫"},
{":guernsey:","🇬🇬"},
{":ghana:","🇬🇭"},
{":gibraltar:","🇬🇮"},
{":greenland:","🇬🇱"},
{":gambia:","🇬🇲"},
{":guinea:","🇬🇳"},
{":guadeloupe:","🇬🇵"},
{":equatorial_guinea:","🇬🇶"},
{":greece:","🇬🇷"},
{":south_georgia_south_sandwich_islands:","🇬🇸"},
{":guatemala:","🇬🇹"},
{":guam:","🇬🇺"},
{":guinea_bissau:","🇬🇼"},
{":guyana:","🇬🇾"},
{":hong_kong:","🇭🇰"},
{":heard_mcdonald_islands:","🇭🇲"},
{":honduras:","🇭🇳"},
{":croatia:","🇭🇷"},
{":haiti:","🇭🇹"},
{":hungary:","🇭🇺"},
{":canary_islands:","🇮🇨"},
{":indonesia:","🇮🇩"},
{":ireland:","🇮🇪"},
{":israel:","🇮🇱"},
{":isle_of_man:","🇮🇲"},
{":india:","🇮🇳"},
{":british_indian_ocean_territory:","🇮🇴"},
{":iraq:","🇮🇶"},
{":iran:","🇮🇷"},
{":iceland:","🇮🇸"},
{":jersey:","🇯🇪"},
{":jamaica:","🇯🇲"},
{":jordan:","🇯🇴"},
{":kenya:","🇰🇪"},
{":kyrgyzstan:","🇰🇬"},
{":cambodia:","🇰🇭"},
{":kiribati:","🇰🇮"},
{":comoros:","🇰🇲"},
{":st_kitts_nevis:","🇰🇳"},
{":north_korea:","🇰🇵"},
{":kuwait:","🇰🇼"},
{":cayman_islands:","🇰🇾"},
{":kazakhstan:","🇰🇿"},
{":laos:","🇱🇦"},
{":lebanon:","🇱🇧"},
{":st_lucia:","🇱🇨"},
{":liechtenstein:","🇱🇮"},
{":sri_lanka:","🇱🇰"},
{":liberia:","🇱🇷"},
{":lesotho:","🇱🇸"},
{":lithuania:","🇱🇹"},
{":luxembourg:","🇱🇺"},
{":latvia:","🇱🇻"},
{":libya:","🇱🇾"},
{":morocco:","🇲🇦"},
{":monaco:","🇲🇨"},
{":moldova:","🇲🇩"},
{":montenegro:","🇲🇪"},
{":st_martin:","🇲🇫"},
{":madagascar:","🇲🇬"},
{":marshall_islands:","🇲🇭"},
{":macedonia:","🇲🇰"},
{":mali:","🇲🇱"},
{":myanmar:","🇲🇲"},
{":mongolia:","🇲🇳"},
{":macau:","🇲🇴"},
{":northern_mariana_islands:","🇲🇵"},
{":martinique:","🇲🇶"},
{":mauritania:","🇲🇷"},
{":montserrat:","🇲🇸"},
{":malta:","🇲🇹"},
{":mauritius:","🇲🇺"},
{":maldives:","🇲🇻"},
{":malawi:","🇲🇼"},
{":mexico:","🇲🇽"},
{":malaysia:","🇲🇾"},
{":mozambique:","🇲🇿"},
{":namibia:","🇳🇦"},
{":new_caledonia:","🇳🇨"},
{":niger:","🇳🇪"},
{":norfolk_island:","🇳🇫"},
{":nigeria:","🇳🇬"},
{":nicaragua:","🇳🇮"},
{":netherlands:","🇳🇱"},
{":norway:","🇳🇴"},
{":nepal:","🇳🇵"},
{":nauru:","🇳🇷"},
{":niue:","🇳🇺"},
{":new_zealand:","🇳🇿"},
{":oman:","🇴🇲"},
{":panama:","🇵🇦"},
{":peru:","🇵🇪"},
{":french_polynesia:","🇵🇫"},
{":papua_new_guinea:","🇵🇬"},
{":philippines:","🇵🇭"},
{":pakistan:","🇵🇰"},
{":poland:","🇵🇱"},
{":st_pierre_miquelon:","🇵🇲"},
{":pitcairn_islands:","🇵🇳"},
{":puerto_rico:","🇵🇷"},
{":palestinian_territories:","🇵🇸"},
{":portugal:","🇵🇹"},
{":palau:","🇵🇼"},
{":paraguay:","🇵🇾"},
{":qatar:","🇶🇦"},
{":reunion:","🇷🇪"},
{":romania:","🇷🇴"},
{":serbia:","🇷🇸"},
{":rwanda:","🇷🇼"},
{":saudi_arabia:","🇸🇦"},
{":solomon_islands:","🇸🇧"},
{":seychelles:","🇸🇨"},
{":sudan:","🇸🇩"},
{":sweden:","🇸🇪"},
{":singapore:","🇸🇬"},
{":st_helena:","🇸🇭"},
{":slovenia:","🇸🇮"},
{":svalbard_jan_mayen:","🇸🇯"},
{":slovakia:","🇸🇰"},
{":sierra_leone:","🇸🇱"},
{":san_marino:","🇸🇲"},
{":senegal:","🇸🇳"},
{":somalia:","🇸🇴"},
{":suriname:","🇸🇷"},
{":south_sudan:","🇸🇸"},
{":sao_tome_principe:","🇸🇹"},
{":el_salvador:","🇸🇻"},
{":sint_maarten:","🇸🇽"},
{":syria:","🇸🇾"},
{":swaziland:","🇸🇿"},
{":tristan_da_cunha:","🇹🇦"},
{":turks_caicos_islands:","🇹🇨"},
{":chad:","🇹🇩"},
{":french_southern_territories:","🇹🇫"},
{":togo:","🇹🇬"},
{":thailand:","🇹🇭"},
{":tajikistan:","🇹🇯"},
{":tokelau:","🇹🇰"},
{":timor_leste:","🇹🇱"},
{":turkmenistan:","🇹🇲"},
{":tunisia:","🇹🇳"},
{":tonga:","🇹🇴"},
{":tr:","🇹🇷"},
{":trinidad_tobago:","🇹🇹"},
{":tuvalu:","🇹🇻"},
{":taiwan:","🇹🇼"},
{":tanzania:","🇹🇿"},
{":ukraine:","🇺🇦"},
{":uganda:","🇺🇬"},
{":us_outlying_islands:","🇺🇲"},
{":united_nations:","🇺🇳"},
{":uruguay:","🇺🇾"},
{":uzbekistan:","🇺🇿"},
{":vatican_city:","🇻🇦"},
{":st_vincent_grenadines:","🇻🇨"},
{":venezuela:","🇻🇪"},
{":british_virgin_islands:","🇻🇬"},
{":us_virgin_islands:","🇻🇮"},
{":vietnam:","🇻🇳"},
{":vanuatu:","🇻🇺"},
{":wallis_futuna:","🇼🇫"},
{":samoa:","🇼🇸"},
{":kosovo:","🇽🇰"},
{":yemen:","🇾🇪"},
{":mayotte:","🇾🇹"},
{":south_africa:","🇿🇦"},
{":zambia:","🇿🇲"},
{":zimbabwe:","🇿🇼"}
};
SmileyToEmojiDefault = new Dictionary<string, string>()
@@ -1039,31 +1766,31 @@ namespace Markdig.Extensions.Emoji
{"<=", ":custom_arrow_left_strong:" },
{"=>", ":custom_arrow_right_strong:" },
{"<=>", ":custom_arrow_left_right_strong:" },
};
// Build Emoji and Smiley CompactPrefixTree
EmojiPrefixTreeDefault = new CompactPrefixTree<string>(EmojiToUnicodeDefault);
int jointCount = EmojiToUnicodeDefault.Count + SmileyToEmojiDefault.Count;
// Count * 2 seems to be a good fit for the data set
EmojiSmileyPrefixTreeDefault = new CompactPrefixTree<string>(jointCount, jointCount * 2, jointCount * 2);
// This is not the best data set for the prefix tree as it will have to check the first character linearly
// A work-around would require a bunch of substrings / removing the leading ':' from emojis, neither one is pretty
// This way we sacrifice a few microseconds for not introducing breaking changes, emojis aren't all that common anyhow
};
// Build Emoji and Smiley CompactPrefixTree
EmojiPrefixTreeDefault = new CompactPrefixTree<string>(EmojiToUnicodeDefault);
int jointCount = EmojiToUnicodeDefault.Count + SmileyToEmojiDefault.Count;
// Count * 2 seems to be a good fit for the data set
EmojiSmileyPrefixTreeDefault = new CompactPrefixTree<string>(jointCount, jointCount * 2, jointCount * 2);
// This is not the best data set for the prefix tree as it will have to check the first character linearly
// A work-around would require a bunch of substrings / removing the leading ':' from emojis, neither one is pretty
// This way we sacrifice a few microseconds for not introducing breaking changes, emojis aren't all that common anyhow
var firstChars = new HashSet<char> { ':' };
foreach (var emoji in EmojiToUnicodeDefault)
foreach (var emoji in EmojiToUnicodeDefault)
EmojiSmileyPrefixTreeDefault.Add(emoji);
foreach (var smiley in SmileyToEmojiDefault)
{
if (!EmojiToUnicodeDefault.TryGetValue(smiley.Value, out string unicode))
throw new ArgumentException("Invalid smiley target: {0} is not present in the emoji dictionary", smiley.Value);
firstChars.Add(smiley.Key[0]);
if (!EmojiSmileyPrefixTreeDefault.TryAdd(smiley.Key, unicode))
throw new ArgumentException("Smiley {0} is already present in the Emoji dictionary", smiley.Key);
foreach (var smiley in SmileyToEmojiDefault)
{
if (!EmojiToUnicodeDefault.TryGetValue(smiley.Value, out string unicode))
throw new ArgumentException("Invalid smiley target: {0} is not present in the emoji dictionary", smiley.Value);
firstChars.Add(smiley.Key[0]);
if (!EmojiSmileyPrefixTreeDefault.TryAdd(smiley.Key, unicode))
throw new ArgumentException("Smiley {0} is already present in the Emoji dictionary", smiley.Key);
}
EmojiOpeningCharactersDefault = new[] { ':' };

View File

@@ -1,4 +1,4 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
@@ -16,7 +16,7 @@ namespace Markdig.Extensions.GenericAttributes
/// Extension that allows to attach HTML attributes to the previous <see cref="Inline"/> or current <see cref="Block"/>.
/// This extension should be enabled last after enabling other extensions.
/// </summary>
/// <seealso cref="Markdig.IMarkdownExtension" />
/// <seealso cref="IMarkdownExtension" />
public class GenericAttributesExtension : IMarkdownExtension
{
public void Setup(MarkdownPipelineBuilder pipeline)
@@ -29,8 +29,7 @@ namespace Markdig.Extensions.GenericAttributes
// Plug into all IAttributesParseable
foreach (var parser in pipeline.BlockParsers)
{
var attributesParseable = parser as IAttributesParseable;
if (attributesParseable != null)
if (parser is IAttributesParseable attributesParseable)
{
attributesParseable.TryParseAttributes = TryProcessAttributesForHeading;
}
@@ -53,8 +52,7 @@ namespace Markdig.Extensions.GenericAttributes
var copy = line;
copy.Start = indexOfAttributes;
var startOfAttributes = copy.Start;
HtmlAttributes attributes;
if (GenericAttributesParser.TryParse(ref copy, out attributes))
if (GenericAttributesParser.TryParse(ref copy, out HtmlAttributes attributes))
{
var htmlAttributes = block.GetAttributes();
attributes.CopyTo(htmlAttributes);

View File

@@ -14,7 +14,7 @@ namespace Markdig.Extensions.GenericAttributes
/// <summary>
/// An inline parser used to parse a HTML attributes that can be attached to the previous <see cref="Inline"/> or current <see cref="Block"/>.
/// </summary>
/// <seealso cref="Markdig.Parsers.InlineParser" />
/// <seealso cref="InlineParser" />
public class GenericAttributesParser : InlineParser
{
/// <summary>
@@ -27,9 +27,8 @@ namespace Markdig.Extensions.GenericAttributes
public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
HtmlAttributes attributes;
var startPosition = slice.Start;
if (TryParse(ref slice, out attributes))
if (TryParse(ref slice, out HtmlAttributes attributes))
{
var inline = processor.Inline;
@@ -50,8 +49,10 @@ namespace Markdig.Extensions.GenericAttributes
// If the current block is a Paragraph, but only the HtmlAttributes is used,
// Try to attach the attributes to the following block
var paragraph = objectToAttach as ParagraphBlock;
if (paragraph != null && paragraph.Inline.FirstChild == null && processor.Inline == null && slice.IsEmptyOrWhitespace())
if (objectToAttach is ParagraphBlock paragraph &&
paragraph.Inline.FirstChild == null &&
processor.Inline == null &&
slice.IsEmptyOrWhitespace())
{
var parent = paragraph.Parent;
var indexOfParagraph = parent.IndexOf(paragraph);
@@ -67,9 +68,7 @@ namespace Markdig.Extensions.GenericAttributes
attributes.CopyTo(currentHtmlAttributes, true, false);
// Update the position of the attributes
int line;
int column;
currentHtmlAttributes.Span.Start = processor.GetSourcePosition(startPosition, out line, out column);
currentHtmlAttributes.Span.Start = processor.GetSourcePosition(startPosition, out int line, out int column);
currentHtmlAttributes.Line = line;
currentHtmlAttributes.Column = column;
currentHtmlAttributes.Span.End = currentHtmlAttributes.Span.Start + slice.Start - startPosition - 1;
@@ -223,6 +222,7 @@ namespace Markdig.Extensions.GenericAttributes
{
// Parse until we match a space or a special html character
startValue = line.Start;
bool valid = false;
while (true)
{
if (c == '\0')
@@ -234,9 +234,10 @@ namespace Markdig.Extensions.GenericAttributes
break;
}
c = line.NextChar();
valid = true;
}
endValue = line.Start - 1;
if (endValue == startValue)
if (!valid)
{
break;
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using System;
@@ -10,7 +10,7 @@ namespace Markdig.Extensions.SmartyPants
/// <summary>
/// A HTML renderer for a <see cref="SmartyPant"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Html.HtmlObjectRenderer{SmartyPant}" />
/// <seealso cref="HtmlObjectRenderer{SmartyPant}" />
public class HtmlSmartyPantRenderer : HtmlObjectRenderer<SmartyPant>
{
private static readonly SmartyPantOptions DefaultOptions = new SmartyPantOptions();
@@ -21,17 +21,15 @@ namespace Markdig.Extensions.SmartyPants
/// Initializes a new instance of the <see cref="HtmlSmartyPantRenderer"/> class.
/// </summary>
/// <param name="options">The options.</param>
/// <exception cref="System.ArgumentNullException"></exception>
/// <exception cref="ArgumentNullException"></exception>
public HtmlSmartyPantRenderer(SmartyPantOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
this.options = options;
this.options = options ?? throw new ArgumentNullException(nameof(options));
}
protected override void Write(HtmlRenderer renderer, SmartyPant obj)
{
string text;
if (!options.Mapping.TryGetValue(obj.Type, out text))
if (!options.Mapping.TryGetValue(obj.Type, out string text))
{
DefaultOptions.Mapping.TryGetValue(obj.Type, out text);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using System.Diagnostics;
@@ -45,5 +45,15 @@ namespace Markdig.Extensions.SmartyPants
}
return OpeningCharacter != 0 ? OpeningCharacter.ToString() : string.Empty;
}
public LiteralInline AsLiteralInline()
{
return new LiteralInline(ToString())
{
Span = Span,
Line = Line,
Column = Column,
};
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
@@ -37,8 +37,7 @@ namespace Markdig.Extensions.SmartyPants
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
var htmlRenderer = renderer as HtmlRenderer;
if (htmlRenderer != null)
if (renderer is HtmlRenderer htmlRenderer)
{
if (!htmlRenderer.ObjectRenderers.Contains<HtmlSmartyPantRenderer>())
{

View File

@@ -95,9 +95,7 @@ namespace Markdig.Extensions.SmartyPants
// Skip char
c = slice.NextChar();
bool canOpen;
bool canClose;
CharHelper.CheckOpenCloseDelimiter(pc, c, false, out canOpen, out canClose);
CharHelper.CheckOpenCloseDelimiter(pc, c, false, out bool canOpen, out bool canClose);
bool postProcess = false;
@@ -156,11 +154,9 @@ namespace Markdig.Extensions.SmartyPants
}
// Create the SmartyPant inline
int line;
int column;
var pant = new SmartyPant()
{
Span = {Start = processor.GetSourcePosition(startingPosition, out line, out column)},
Span = { Start = processor.GetSourcePosition(startingPosition, out int line, out int column) },
Line = line,
Column = column,
OpeningCharacter = openingChar,
@@ -195,96 +191,90 @@ namespace Markdig.Extensions.SmartyPants
return quotePants;
}
private struct Opener
{
public int Type;
public int Index;
public Opener(int type, int index)
{
Type = type;
Index = index;
}
}
private void BlockOnProcessInlinesEnd(InlineProcessor processor, Inline inline)
{
processor.Block.ProcessInlinesEnd -= BlockOnProcessInlinesEnd;
var pants = (ListSmartyPants) processor.ParserStates[Index];
// We only change quote into left or right quotes if we find proper balancing
var previousIndices = new int[3] {-1, -1, -1};
Stack<Opener> openers = new Stack<Opener>(4);
for (int i = 0; i < pants.Count; i++)
{
var quote = pants[i];
var quoteType = quote.Type;
int currentTypeIndex = -1;
SmartyPantType expectedLeftQuote = 0;
SmartyPantType expectedRightQuote = 0;
int type;
bool isLeft;
if (quote.Type == SmartyPantType.LeftQuote || quote.Type == SmartyPantType.RightQuote)
if (quoteType == SmartyPantType.LeftQuote || quoteType == SmartyPantType.RightQuote)
{
currentTypeIndex = 0;
expectedLeftQuote = SmartyPantType.LeftQuote;
expectedRightQuote = SmartyPantType.RightQuote;
type = 0;
isLeft = quoteType == SmartyPantType.LeftQuote;
}
else if (quote.Type == SmartyPantType.LeftDoubleQuote || quote.Type == SmartyPantType.RightDoubleQuote)
else if (quoteType == SmartyPantType.LeftDoubleQuote || quoteType == SmartyPantType.RightDoubleQuote)
{
currentTypeIndex = 1;
expectedLeftQuote = SmartyPantType.LeftDoubleQuote;
expectedRightQuote = SmartyPantType.RightDoubleQuote;
type = 1;
isLeft = quoteType == SmartyPantType.LeftDoubleQuote;
}
else if (quote.Type == SmartyPantType.LeftAngleQuote || quote.Type == SmartyPantType.RightAngleQuote)
else if (quoteType == SmartyPantType.LeftAngleQuote || quoteType == SmartyPantType.RightAngleQuote)
{
currentTypeIndex = 2;
expectedLeftQuote = SmartyPantType.LeftAngleQuote;
expectedRightQuote = SmartyPantType.RightAngleQuote;
}
if (currentTypeIndex < 0)
{
continue;
}
int previousIndex = previousIndices[currentTypeIndex];
var previousQuote = previousIndex >= 0 ? pants[previousIndex] : null;
if (previousQuote == null)
{
if (quote.Type == expectedLeftQuote)
{
previousIndices[currentTypeIndex] = i;
}
type = 2;
isLeft = quoteType == SmartyPantType.LeftAngleQuote;
}
else
{
if (quote.Type == expectedRightQuote)
{
// Replace all intermediate unmatched left or right SmartyPants to their literal equivalent
pants.RemoveAt(i);
i--;
for (int j = i; j > previousIndex; j--)
{
var toReplace = pants[j];
pants.RemoveAt(j);
toReplace.ReplaceBy(new LiteralInline(toReplace.ToString())
{
Span = toReplace.Span,
Line = toReplace.Line,
Column = toReplace.Column,
});
i--;
}
quote.ReplaceBy(quote.AsLiteralInline());
continue;
}
// If we matched, we remove left/right quotes from the list
pants.RemoveAt(previousIndex);
previousIndices[currentTypeIndex] = -1;
}
else
if (isLeft)
{
openers.Push(new Opener(type, i));
}
else
{
bool found = false;
while (openers.Count > 0)
{
previousIndices[currentTypeIndex] = i;
Opener opener = openers.Pop();
var previousQuote = pants[opener.Index];
if (opener.Type == type)
{
found = true;
break;
}
else
{
previousQuote.ReplaceBy(previousQuote.AsLiteralInline());
}
}
if (!found)
{
quote.ReplaceBy(quote.AsLiteralInline());
}
}
}
// If we have any quotes lefts, replace them by there literal equivalent
foreach (var quote in pants)
foreach (var opener in openers)
{
quote.ReplaceBy(new LiteralInline(quote.ToString())
{
Span = quote.Span,
Line = quote.Line,
Column = quote.Column,
});
var quote = pants[opener.Index];
quote.ReplaceBy(quote.AsLiteralInline());
}
pants.Clear();
@@ -294,8 +284,7 @@ namespace Markdig.Extensions.SmartyPants
bool isFinalProcessing)
{
// Don't try to process anything if there are no dash
var quotePants = state.ParserStates[Index] as ListSmartyPants;
if (quotePants == null || !quotePants.HasDash)
if (!(state.ParserStates[Index] is ListSmartyPants quotePants) || !quotePants.HasDash)
{
return true;
}
@@ -309,10 +298,8 @@ namespace Markdig.Extensions.SmartyPants
{
var next = child.NextSibling;
if (child is LiteralInline)
if (child is LiteralInline literal)
{
var literal = (LiteralInline) child;
var startIndex = 0;
var indexOfDash = literal.Content.IndexOf("--", startIndex);

View File

@@ -118,20 +118,11 @@ namespace Markdig.Helpers
public int IndexOfOpeningCharacter(string text, int start, int end)
{
var maxChar = isOpeningCharacter.Length;
#if SUPPORT_UNSAFE
unsafe
#endif
{
#if SUPPORT_FIXED_STRING
fixed (char* pText = text)
#else
var pText = text;
#endif
#if SUPPORT_UNSAFE
fixed (char* pText = text)
fixed (bool* openingChars = isOpeningCharacter)
#else
var openingChars = isOpeningCharacter;
#endif
{
if (nonAsciiMap == null)
{

View File

@@ -597,20 +597,23 @@ namespace Markdig.Helpers
}
}
if (hasEscape && !c.IsAsciiPunctuation())
if (!isAutoLink)
{
buffer.Append('\\');
}
if (hasEscape && !c.IsAsciiPunctuation())
{
buffer.Append('\\');
}
// If we have an escape
if (c == '\\')
{
hasEscape = true;
c = text.NextChar();
continue;
}
// If we have an escape
if (c == '\\')
{
hasEscape = true;
c = text.NextChar();
continue;
}
hasEscape = false;
hasEscape = false;
}
if (IsEndOfUri(c, isAutoLink))
{
@@ -622,10 +625,7 @@ namespace Markdig.Helpers
{
if (c == '&')
{
int entityNameStart;
int entityNameLength;
int entityValue;
if (HtmlHelper.ScanEntity(text, out entityValue, out entityNameStart, out entityNameLength) > 0)
if (HtmlHelper.ScanEntity(text, out _, out _, out _) > 0)
{
isValid = true;
break;

View File

@@ -1,84 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>A fast, powerful, CommonMark compliant, extensible Markdown processor for .NET with 20+ builtin extensions (pipetables, footnotes, definition lists... etc.)</Description>
<Copyright>Alexandre Mutel</Copyright>
<AssemblyTitle>Markdig</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.17.0</VersionPrefix>
<Authors>Alexandre Mutel</Authors>
<TargetFrameworks>net35;net40;netstandard2.0;uap10.0;netcoreapp2.1</TargetFrameworks>
<AssemblyName>Markdig</AssemblyName>
<PackageId>Markdig</PackageId>
<PackageId Condition="'$(SignAssembly)' == 'true'">Markdig.Signed</PackageId>
<PackageTags>Markdown CommonMark md html md2html</PackageTags>
<PackageReleaseNotes>https://github.com/lunet-io/markdig/blob/master/changelog.md</PackageReleaseNotes>
<PackageLicenseExpression>BSD-2-Clause</PackageLicenseExpression>
<PackageIconUrl>https://raw.githubusercontent.com/lunet-io/markdig/master/img/markdig.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/lunet-io/markdig</PackageProjectUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.1' ">1.6.0</NetStandardImplicitPackageVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'portable40-net40+sl5+win8+wp8+wpa81' ">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net35' ">
<DefineConstants>$(DefineConstants);SUPPORT_FIXED_STRING;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' ">
<DefineConstants>$(DefineConstants);SUPPORT_FIXED_STRING;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);SUPPORT_FIXED_STRING;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">
<DefineConstants>$(DefineConstants);SUPPORT_FIXED_STRING;SUPPORT_UNSAFE;NETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition="'$(TargetPlatformVersion)' == ''">10.0.17763.0</TargetPlatformVersion>
<TargetPlatformMinVersion Condition="'$(TargetPlatformMinVersion)' == ''">10.0.10240.0</TargetPlatformMinVersion>
<DefineConstants>$(DefineConstants);NETSTANDARD_11;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(SignAssembly)' == 'true' ">
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<!-- Special packages and imports for UWP support -->
<ItemGroup>
<PackageReference Include="MSBuild.Sdk.Extras" Version="1.0.9" PrivateAssets="all" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform " Version="5.2.2" />
</ItemGroup>
<Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
<Import Project="Markdig.targets" />
</Project>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Description>A fast, powerful, CommonMark compliant, extensible Markdown processor for .NET with 20+ builtin extensions (pipetables, footnotes, definition lists... etc.)</Description>
<Copyright>Alexandre Mutel</Copyright>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.17.1</VersionPrefix>
<Authors>Alexandre Mutel</Authors>
<TargetFrameworks>net35;net40;netstandard2.0;uap10.0;netcoreapp2.1</TargetFrameworks>
<PackageTags>Markdown CommonMark md html md2html</PackageTags>
<PackageReleaseNotes>https://github.com/lunet-io/markdig/blob/master/changelog.md</PackageReleaseNotes>
<PackageLicenseExpression>BSD-2-Clause</PackageLicenseExpression>
<PackageIconUrl>https://raw.githubusercontent.com/lunet-io/markdig/master/img/markdig.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/lunet-io/markdig</PackageProjectUrl>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition="'$(TargetPlatformVersion)' == ''">10.0.17763.0</TargetPlatformVersion>
<TargetPlatformMinVersion Condition="'$(TargetPlatformMinVersion)' == ''">10.0.10240.0</TargetPlatformMinVersion>
<DefineConstants>$(DefineConstants);UAP</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<!-- Special packages and imports for UWP support -->
<ItemGroup>
<PackageReference Include="MSBuild.Sdk.Extras" Version="1.0.9" PrivateAssets="all" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform " Version="5.2.2" />
</ItemGroup>
<Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
</Project>

View File

@@ -17,7 +17,7 @@ namespace Markdig
/// </summary>
public static partial class Markdown
{
#if NETSTANDARD_11
#if UAP
public static readonly string Version = typeof(Markdown).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
#else
public static readonly string Version = ((AssemblyFileVersionAttribute) typeof(Markdown).Assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0]).Version;

View File

@@ -103,12 +103,12 @@ namespace SpecFileGen
continue;
}
string source = ParseSpecification(spec, File.ReadAllText(spec.Path));
string source = ParseSpecification(spec, File.ReadAllText(spec.Path)).Replace("\r\n", "\n", StringComparison.Ordinal);
totalTests += spec.TestCount;
if (File.Exists(spec.OutputPath)) // If the source hasn't changed, don't bump the generated tag
{
string previousSource = File.ReadAllText(spec.OutputPath);
string previousSource = File.ReadAllText(spec.OutputPath).Replace("\r\n", "\n", StringComparison.Ordinal);
int start = previousSource.IndexOf('\n', StringComparison.Ordinal) + 1;
int previousLength = previousSource.Length - start;
if (start != 0 && previousLength == source.Length)

View File

@@ -13,12 +13,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{061866E2
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdig", "Markdig\Markdig.csproj", "{8A58A7E2-627C-4F41-933F-5AC92ADFAB48}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdig.Signed", "Markdig.Signed\Markdig.Signed.csproj", "{C37C7B94-1219-4ED9-ABAC-C0B4B8FE8750}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markdig.Tests", "Markdig.Tests\Markdig.Tests.csproj", "{A0C5CB5F-5568-40AB-B945-D6D2664D51B0}"
ProjectSection(ProjectDependencies) = postProject
{8A58A7E2-627C-4F41-933F-5AC92ADFAB48} = {8A58A7E2-627C-4F41-933F-5AC92ADFAB48}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markdig.Benchmarks", "Markdig.Benchmarks\Markdig.Benchmarks.csproj", "{6A19F040-BC7C-4283-873A-177B5324F1ED}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdig.Benchmarks", "Markdig.Benchmarks\Markdig.Benchmarks.csproj", "{6A19F040-BC7C-4283-873A-177B5324F1ED}"
ProjectSection(ProjectDependencies) = postProject
{8A58A7E2-627C-4F41-933F-5AC92ADFAB48} = {8A58A7E2-627C-4F41-933F-5AC92ADFAB48}
EndProjectSection
@@ -41,6 +43,10 @@ Global
{8A58A7E2-627C-4F41-933F-5AC92ADFAB48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A58A7E2-627C-4F41-933F-5AC92ADFAB48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A58A7E2-627C-4F41-933F-5AC92ADFAB48}.Release|Any CPU.Build.0 = Release|Any CPU
{C37C7B94-1219-4ED9-ABAC-C0B4B8FE8750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C37C7B94-1219-4ED9-ABAC-C0B4B8FE8750}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C37C7B94-1219-4ED9-ABAC-C0B4B8FE8750}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C37C7B94-1219-4ED9-ABAC-C0B4B8FE8750}.Release|Any CPU.Build.0 = Release|Any CPU
{A0C5CB5F-5568-40AB-B945-D6D2664D51B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0C5CB5F-5568-40AB-B945-D6D2664D51B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0C5CB5F-5568-40AB-B945-D6D2664D51B0}.Release|Any CPU.ActiveCfg = Release|Any CPU