Compare commits

...

24 Commits

Author SHA1 Message Date
Alexandre Mutel
d7fd04d14c Bump to 0.13.4 2017-10-17 23:01:26 +02:00
Alexandre Mutel
2147e434f7 Add support for single table header row without a table body rows (#141) 2017-10-17 22:58:25 +02:00
Alexandre Mutel
7bd00d115f Merge pull request #149 from maulwuff/nomnomlSupport
Nomnoml support
2017-10-17 15:44:17 +02:00
maulwuff
80ef9d2799 doc: added nomnoml specs 2017-10-17 14:54:43 +02:00
maulwuff
d6a705d76c new: support nomnoml diagrams 2017-10-17 14:54:43 +02:00
Alexandre Mutel
42472085a6 Add mdtoc simple tool to generate a markdown TOC from a local markdown file or github link to a markdown file 2017-10-15 23:31:14 +02:00
Alexandre Mutel
3897e875ee Add KeepOpeningDigits and DiscardDots options to AutoIdentifiers to match GitHub behavior 2017-10-15 23:29:02 +02:00
Alexandre Mutel
3628dc3b17 Merge pull request #142 from mlaily/patch-1
Fix typos in EmojiSpecs.md
2017-09-13 22:30:24 +02:00
Melvyn Laïly
89ff42805d Fix typos in EmojiSpecs.md 2017-09-13 22:26:10 +02:00
Alexandre Mutel
9cc5856c1c Bump to 0.13.3 2017-08-30 15:47:54 +02:00
Alexandre Mutel
a4bb174a77 Add .editorconfig 2017-08-30 15:44:08 +02:00
Alexandre Mutel
82987fa879 Merge pull request #139 from kenmuse/enhance/yaml-frontmatter
Implement Pandoc compatible front matter parsing
2017-08-30 15:36:38 +02:00
Ken Muse
2df2ff17c5 Replace tabs with spaces 2017-08-30 09:29:27 -04:00
Ken Muse
4e4825cb3f Implement Pandoc compatible front matter parsing 2017-08-29 18:49:14 -04:00
Alexandre Mutel
ed2371beae Update MSBuild.Sdk.Extras to version 1.0.9 to fix compatibility with pack for uap10.0 2017-08-29 08:06:29 +02:00
Alexandre Mutel
2c2898769e Bump to 0.13.2 2017-08-29 07:48:27 +02:00
Alexandre Mutel
001a99ab77 Add support for UAP10.0 (#137) 2017-08-29 07:48:14 +02:00
Alexandre Mutel
9233ec220c Bump to 0.13.1 2017-08-21 16:23:31 +02:00
Alexandre Mutel
bb30dc21c5 Fix indenting issue after a double digit list block using a tab (#134) 2017-08-21 16:04:47 +02:00
Alexandre Mutel
c761fa2243 Bump to 0.13.0 2017-08-03 19:26:48 +02:00
Alexandre Mutel
9d172ffcc1 Update URL links to accept balanced parenthesis for CommonMark specs 0.28 2017-08-03 19:25:17 +02:00
Alexandre Mutel
1863e22328 Update to emphasis to CommonMark specs 0.28 (when *** prefer em, strong vs strong, em) 2017-08-03 19:20:58 +02:00
Alexandre Mutel
c591d1950f Update CommonMark test specs to 0.28 2017-08-03 19:20:23 +02:00
Alexandre Mutel
339fcc9152 Add signed package link to readme.md (#11) 2017-08-03 14:57:28 +02:00
28 changed files with 4091 additions and 3274 deletions

38
.editorconfig Normal file
View File

@@ -0,0 +1,38 @@
# EditorConfig is awesome:http://EditorConfig.org
# top-most EditorConfig file
root = true
# All Files
[*]
charset = utf-8
end_of_line = crlf
indent_style = space
indent_size = 4
insert_final_newline = false
trim_trailing_whitespace = true
# Solution Files
[*.sln]
indent_style = tab
# XML Project Files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# Configuration Files
[*.{json,xml,yml,config,props,targets,nuspec,resx,ruleset}]
indent_size = 2
# Markdown Files
[*.md]
trim_trailing_whitespace = false
# Web Files
[*.{htm,html,js,ts,css,scss,less}]
indent_size = 2
insert_final_newline = true
# Bash Files
[*.sh]
end_of_line = lf

View File

@@ -14,7 +14,7 @@ You can **try Markdig online** and compare it to other implementations on [babel
- **Abstract Syntax Tree** with precise source code location for syntax tree, useful when building a Markdown editor.
- Checkout [MarkdownEditor for Visual Studio](https://visualstudiogallery.msdn.microsoft.com/eaab33c3-437b-4918-8354-872dfe5d1bfe) powered by Markdig!
- Converter to **HTML**
- Passing more than **600+ tests** from the latest [CommonMark specs (0.27)](http://spec.commonmark.org/)
- Passing more than **600+ tests** from the latest [CommonMark specs (0.28)](http://spec.commonmark.org/)
- Includes all the core elements of CommonMark:
- including **GFM fenced code blocks**.
- **Extensible** architecture
@@ -47,7 +47,7 @@ You can **try Markdig online** and compare it to other implementations on [babel
- [**Emoji**](src/Markdig.Tests/Specs/EmojiSpecs.md) support (inspired from [Markdown-it](https://markdown-it.github.io/))
- [**SmartyPants**](src/Markdig.Tests/Specs/SmartyPantsSpecs.md) (inspired from [Daring Fireball - SmartyPants](https://daringfireball.net/projects/smartypants/))
- [**Bootstrap**](src/Markdig.Tests/Specs/BootstrapSpecs.md) class (to output bootstrap class)
- [**Diagrams**](src/Markdig.Tests/Specs/DiagramsSpecs.md) extension whenever a fenced code block contains a special keyword, it will be converted to a div block with the content as-is (currently, supports only for [`mermaid` diagrams](https://knsv.github.io/mermaid/))
- [**Diagrams**](src/Markdig.Tests/Specs/DiagramsSpecs.md) extension whenever a fenced code block contains a special keyword, it will be converted to a div block with the content as-is (currently, supports [`mermaid`](https://knsv.github.io/mermaid/) and [`nomnoml`](https://github.com/skanaar/nomnoml) diagrams)
- [**YAML frontmatter**](src/Markdig.Tests/Specs/YamlSpecs.md) to parse without evaluating the frontmatter and to discard it from the HTML output (typically used for previewing without the frontmatter in MarkdownEditor)
- [**JIRA links**](src/Markdig.Tests/Specs/JiraLinks.md) to automatically generate links for JIRA project references (Thanks to @clarkd: https://github.com/clarkd/MarkdigJiraLinker)
- Compatible with .NET 3.5, 4.0+ and .NET Core (`netstandard1.1+`)
@@ -64,6 +64,8 @@ In the meantime, you can have a "behind the scene" article about Markdig in my b
Markdig is available as a NuGet package: [![NuGet](https://img.shields.io/nuget/v/Markdig.svg)](https://www.nuget.org/packages/Markdig/)
Also [Markdig.Signed](https://www.nuget.org/packages/Markdig.Signed/) NuGet package provides signed assemblies.
## Usage
The main entry point for the API is the `Markdig.Markdown` class:

View File

@@ -23,4 +23,35 @@ graph TD;
</div>
````````````````````````````````
## nomnoml diagrams
Using a fenced code block with the `nomnoml` language info will output a `<div class='nomnoml'>` instead of a `pre/code` block:
```````````````````````````````` example
```nomnoml
[example|
propertyA: Int
propertyB: string
|
methodA()
methodB()
|
[subA]--[subB]
[subA]-:>[sub C]
]
```
.
<div class="nomnoml">[example|
propertyA: Int
propertyB: string
|
methodA()
methodB()
|
[subA]--[subB]
[subA]-:>[sub C]
]
</div>
````````````````````````````````
TODO: Add other text diagram languages

View File

@@ -31,9 +31,9 @@ We all need :), it makes us :muscle:. (and :ok_hand:).
Sentences can end with Emoji:
```````````````````````````````` example
This is a sentance :ok_hand:
This is a sentence :ok_hand:
and keeps going to the next line :)
.
<p>This is a sentance 👌
<p>This is a sentence 👌
and keeps going to the next line 😃</p>
````````````````````````````````
````````````````````````````````

View File

@@ -513,6 +513,39 @@ a | b
</table>
````````````````````````````````
** Rule #9**
It is possible to have a single row header only:
```````````````````````````````` example
a | b
-- | --
.
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
</table>
````````````````````````````````
```````````````````````````````` example
|a|b|c
|---|---|---|
.
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
</tr>
</thead>
</table>
````````````````````````````````
** Tests **
Tests trailing spaces after pipes

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<#/*
<#/*
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.The MIT License (MIT)
@@ -36,9 +36,10 @@ SOFTWARE.
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.CodeDom" #>
<#@ import namespace="System.CodeDom.Compiler" #>
<#@ output extension=".cs" #><#
<#@ output extension=".cs" encoding="utf-8"#>
<#
var specFiles = new KeyValuePair<string, string>[] {
new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/791b1c121f16d3d7e80837c6f52917e57bbb2f61/spec.txt", string.Empty), // 0.27
new KeyValuePair<string, string>("https://raw.githubusercontent.com/jgm/CommonMark/4ec06917c3a3632be4a935ffa0973092bd2621be/spec.txt", string.Empty), // 0.28
new KeyValuePair<string, string>(Host.ResolvePath("PipeTableSpecs.md"), "pipetables|advanced"),
new KeyValuePair<string, string>(Host.ResolvePath("FootnotesSpecs.md"), "footnotes|advanced"),
new KeyValuePair<string, string>(Host.ResolvePath("GenericAttributesSpecs.md"), "attributes|advanced"),

View File

@@ -13,13 +13,13 @@ namespace Markdig.Tests
[Test]
public void StrongNormal()
{
TestParser.TestSpec("***Strong emphasis*** normal", "<p><strong><em>Strong emphasis</em></strong> normal</p>", "");
TestParser.TestSpec("***Strong emphasis*** normal", "<p><em><strong>Strong emphasis</strong></em> normal</p>", "");
}
[Test]
public void NormalStrongNormal()
{
TestParser.TestSpec("normal ***Strong emphasis*** normal", "<p>normal <strong><em>Strong emphasis</em></strong> normal</p>", "");
TestParser.TestSpec("normal ***Strong emphasis*** normal", "<p>normal <em><strong>Strong emphasis</strong></em> normal</p>", "");
}
}
}

View File

@@ -42,3 +42,62 @@ This is a text
<p>This is a text</p>
````````````````````````````````
It can end with three dots `...`:
```````````````````````````````` example
---
this: is a frontmatter
...
This is a text
.
<p>This is a text</p>
````````````````````````````````
It expects exactly three dots `...`:
```````````````````````````````` example
---
this: is a frontmatter
....
This is a text
.
````````````````````````````````
Front matter ends with the first line containing three dots `...` or three dashes `...`:
```````````````````````````````` example
---
this: is a frontmatter
....
Hello
---
This is a text
.
<p>This is a text</p>
````````````````````````````````
It expects whitespace can exist after the leading characters
```````````````````````````````` example
---
this: is a frontmatter
...
This is a text
.
<p>This is a text</p>
````````````````````````````````
It expects whitespace can exist after the trailing characters
```````````````````````````````` example
---
this: is a frontmatter
...
This is a text
.
<p>This is a text</p>
````````````````````````````````

View File

@@ -12,6 +12,18 @@ namespace Markdig.Tests
[TestFixture]
public class TestPlayParser
{
[Test]
public void TestListBug2()
{
TestParser.TestSpec("10.\t*test* test\n\n11.\t__test__ test\n\n", @"<ol start=""10"">
<li><p><em>test</em> test</p>
</li>
<li><p><strong>test</strong> test</p>
</li>
</ol>
");
}
[Test]
public void TestSimple()
{

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.
@@ -143,7 +143,12 @@ namespace Markdig.Extensions.AutoIdentifiers
stripRenderer.Render(headingBlock.Inline);
var headingText = headingWriter.ToString();
headingWriter.GetStringBuilder().Length = 0;
headingText = LinkHelper.Urilize(headingText, (options & AutoIdentifierOptions.AllowOnlyAscii) != 0);
// TODO: Should we have a struct with more configure optionss for LinkHelper.Urilize?
headingText = LinkHelper.Urilize(headingText,
(options & AutoIdentifierOptions.AllowOnlyAscii) != 0,
(options & AutoIdentifierOptions.KeepOpeningDigits) != 0,
(options & AutoIdentifierOptions.DiscardDots) != 0);
var baseHeadingId = string.IsNullOrEmpty(headingText) ? "section" : headingText;
int index = 0;

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;
@@ -21,6 +21,11 @@ namespace Markdig.Extensions.AutoIdentifiers
/// </summary>
Default = AutoLink | AllowOnlyAscii,
/// <summary>
/// Renders auto identifiers like GitHub.
/// </summary>
GitHub = Default | KeepOpeningDigits | DiscardDots,
/// <summary>
/// Allows to link to a header by using the same text as the header for the link label. Default is <c>true</c>
/// </summary>
@@ -30,5 +35,15 @@ namespace Markdig.Extensions.AutoIdentifiers
/// Allows only ASCII characters in the url (HTML 5 allows to have UTF8 characters). Default is <c>true</c>
/// </summary>
AllowOnlyAscii = 2,
/// <summary>
/// Allows to keep digits starting a heading (by default, it keeps only characters starting from the first letter)
/// </summary>
KeepOpeningDigits = 4,
/// <summary>
/// Discard dots when computing an identifier.
/// </summary>
DiscardDots = 8
}
}

View File

@@ -25,6 +25,7 @@ namespace Markdig.Extensions.Diagrams
var codeRenderer = htmlRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>();
// TODO: Add other well known diagram languages
codeRenderer.BlocksAsDiv.Add("mermaid");
codeRenderer.BlocksAsDiv.Add("nomnoml");
}
}
}

View File

@@ -85,7 +85,7 @@ namespace Markdig.Extensions.Tables
{
renderer.Write($" rowspan=\"{cell.RowSpan}\"");
}
if (table.ColumnDefinitions != null)
if (table.ColumnDefinitions.Count > 0)
{
var columnIndex = cell.ColumnIndex < 0 || cell.ColumnIndex >= table.ColumnDefinitions.Count
? i

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.
namespace Markdig.Extensions.Tables

View File

@@ -440,12 +440,13 @@ namespace Markdig.Extensions.Tables
// If we have a header row, we can remove it
// TODO: we could optimize this by merging FindHeaderRow and the previous loop
var tableRow = (TableRow)table[0];
tableRow.IsHeader = Options.RequireHeaderSeparator;
if (aligns != null)
{
table.RemoveAt(1);
var tableRow = (TableRow) table[0];
table.ColumnDefinitions.AddRange(aligns);
tableRow.IsHeader = true;
table.RemoveAt(1);
table.ColumnDefinitions.AddRange(aligns);
}
// Perform delimiter processor that are coming after this processor
@@ -532,6 +533,13 @@ namespace Markdig.Extensions.Tables
? columnDelimiter.FirstChild
: delimiter.NextSibling;
// If there is no content after
if (IsNullOrSpace(nextSibling))
{
isValidRow = true;
break;
}
if (!ParseHeaderString(nextSibling, out align))
{
break;
@@ -606,6 +614,20 @@ namespace Markdig.Extensions.Tables
}
}
private static bool IsNullOrSpace(Inline inline)
{
if (inline == null)
{
return true;
}
var literal = inline as LiteralInline;
if (literal != null)
{
return literal.Content.IsEmptyOrWhitespace();
}
return false;
}
private class TableState
{
public TableState()

View File

@@ -33,7 +33,7 @@ namespace Markdig.Extensions.Tables
/// <summary>
/// Gets or sets the column alignments. May be null.
/// </summary>
public List<TableColumnDefinition> ColumnDefinitions { get; private set; }
public List<TableColumnDefinition> ColumnDefinitions { get; }
/// <summary>
/// Checks if the table structure is valid.

View File

@@ -10,7 +10,7 @@ namespace Markdig.Extensions.Yaml
/// A YAML frontmatter block.
/// </summary>
/// <seealso cref="Markdig.Syntax.CodeBlock" />
public class YamlFrontMatterBlock : CodeBlock, IFencedBlock
public class YamlFrontMatterBlock : CodeBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="YamlFrontMatterBlock"/> class.
@@ -19,13 +19,5 @@ namespace Markdig.Extensions.Yaml
public YamlFrontMatterBlock(BlockParser parser) : base(parser)
{
}
public string Info { get; set; }
public string Arguments { get; set; }
public int FencedCharCount { get; set; }
public char FencedChar { get; set; }
}
}

View File

@@ -1,44 +1,128 @@
// 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 Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Syntax;
namespace Markdig.Extensions.Yaml
{
/// <summary>
/// Block parser for a YAML frontmatter.
/// </summary>
/// <seealso cref="Markdig.Parsers.FencedBlockParserBase{YamlFrontMatterBlock}" />
public class YamlFrontMatterParser : FencedBlockParserBase<YamlFrontMatterBlock>
/// <seealso cref="YamlFrontMatterBlock" />
public class YamlFrontMatterParser : BlockParser
{
// We reuse a FencedCodeBlock parser to grab a frontmatter, only active if it happens on the first line of the document.
/// <summary>
/// Initializes a new instance of the <see cref="FencedCodeBlockParser"/> class.
/// Initializes a new instance of the <see cref="YamlFrontMatterParser"/> class.
/// </summary>
public YamlFrontMatterParser()
{
OpeningCharacters = new[] { '-' };
InfoPrefix = null;
// We expect only 3 --- at the beginning of the file no more, no less
MinimumMatchCount = 3;
MaximumMatchCount = 3;
this.OpeningCharacters = new[] { '-' };
}
protected override YamlFrontMatterBlock CreateFencedBlock(BlockProcessor processor)
/// <summary>
/// Creates the front matter block.
/// </summary>
/// <param name="processor">The block processor</param>
/// <returns>The front matter block</returns>
protected virtual YamlFrontMatterBlock CreateFrontMatterBlock(BlockProcessor processor)
{
return new YamlFrontMatterBlock(this);
}
/// <summary>
/// Tries to match a block opening.
/// </summary>
/// <param name="processor">The parser processor.</param>
/// <returns>The result of the match</returns>
public override BlockState TryOpen(BlockProcessor processor)
{
// Only accept a frontmatter at the beginning of the file
if (processor.LineIndex != 0)
// We expect no indentation for a fenced code block.
if (processor.IsCodeIndent)
{
return BlockState.None;
}
return base.TryOpen(processor);
// Only accept a frontmatter at the beginning of the file
if (processor.Start != 0)
{
return BlockState.None;
}
int count = 0;
var line = processor.Line;
char c = line.CurrentChar;
// Must consist of exactly three dashes
while (c == '-' && count < 4)
{
count++;
c = line.NextChar();
}
// If three dashes (optionally followed by whitespace)
// this is a YAML front matter blcok
if (count == 3 && (c == '\0' || c.IsWhitespace()) && line.TrimEnd())
{
// Create a front matter block
var block = this.CreateFrontMatterBlock(processor);
block.Column = processor.Column;
block.Span.Start = 0;
block.Span.End = line.Start;
// Store the number of matched string into the context
processor.NewBlocks.Push(block);
// Discard the current line as it is already parsed
return BlockState.ContinueDiscard;
}
return BlockState.None;
}
/// <summary>
/// Tries to continue matching a block already opened.
/// </summary>
/// <param name="processor">The parser processor.</param>
/// <param name="block">The block already opened.</param>
/// <returns>The result of the match. By default, don't expect any newline</returns>
public override BlockState TryContinue(BlockProcessor processor, Block block)
{
char matchChar;
int count = 0;
var c = processor.CurrentChar;
// Determine if we have a closing fence.
// It can start or end with either <c>---</c> or <c>...</c>
var line = processor.Line;
if (processor.Column == 0 && (c == '-' || c == '.'))
{
matchChar = c;
while (c == matchChar)
{
c = line.NextChar();
count++;
}
// If we have a closing fence, close it and discard the current line
// The line must contain only fence characters and optional following whitespace.
if (count == 3 && !processor.IsCodeIndent && (c == '\0' || c.IsWhitespace()) && line.TrimEnd())
{
block.UpdateSpanEnd(line.Start - 1);
// Don't keep the last line
return BlockState.BreakDiscard;
}
}
// Reset the indentation to the column before the indent
processor.GoToColumn(processor.ColumnBeforeIndent);
return BlockState.Continue;
}
}
}

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;
@@ -18,10 +18,10 @@ namespace Markdig.Helpers
return TryParseAutolink(ref text, out link, out isEmail);
}
public static string Urilize(string headingText, bool allowOnlyAscii)
public static string Urilize(string headingText, bool allowOnlyAscii, bool keepOpeningDigits = false, bool discardDots = false)
{
var headingBuffer = StringBuilderCache.Local();
bool hasLetter = false;
bool hasLetter = keepOpeningDigits && headingText.Length > 0 && char.IsLetterOrDigit(headingText[0]);
bool previousIsSpace = false;
for (int i = 0; i < headingText.Length; i++)
{
@@ -47,7 +47,7 @@ namespace Markdig.Helpers
}
else if (hasLetter)
{
if (IsReservedPunctuation(c))
if (IsReservedPunctuation(c, discardDots))
{
if (previousIsSpace)
{
@@ -67,7 +67,7 @@ namespace Markdig.Helpers
else if (!previousIsSpace && c.IsWhitespace())
{
var pc = headingBuffer[headingBuffer.Length - 1];
if (!IsReservedPunctuation(pc))
if (!IsReservedPunctuation(pc, discardDots))
{
headingBuffer.Append('-');
}
@@ -81,7 +81,7 @@ namespace Markdig.Helpers
while (headingBuffer.Length > 0)
{
var c = headingBuffer[headingBuffer.Length - 1];
if (IsReservedPunctuation(c))
if (IsReservedPunctuation(c, false))
{
headingBuffer.Length--;
}
@@ -97,9 +97,9 @@ namespace Markdig.Helpers
}
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
private static bool IsReservedPunctuation(char c)
private static bool IsReservedPunctuation(char c, bool discardDots)
{
return c == '_' || c == '-' || c == '.';
return c == '_' || c == '-' || (!discardDots && c == '.');
}
public static bool TryParseAutolink(ref StringSlice text, out string link, out bool isEmail)
@@ -561,10 +561,6 @@ namespace Markdig.Helpers
{
if (!hasEscape)
{
if (openedParent > 0)
{
break;
}
openedParent++;
}
}
@@ -613,6 +609,11 @@ namespace Markdig.Helpers
c = text.NextChar();
}
if (openedParent > 0)
{
isValid = false;
}
}
link = isValid ? buffer.ToString() : null;

View File

@@ -5,17 +5,25 @@
<Copyright>Alexandre Mutel</Copyright>
<AssemblyTitle>Markdig</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.12.4</VersionPrefix>
<VersionPrefix>0.13.4</VersionPrefix>
<Authors>Alexandre Mutel</Authors>
<TargetFrameworks>net35;net40;portable40-net40+sl5+win8+wp8+wpa81;netstandard1.1</TargetFrameworks>
<TargetFrameworks>net35;net40;portable40-net40+sl5+win8+wp8+wpa81;netstandard1.1;uap10.0</TargetFrameworks>
<AssemblyName>Markdig</AssemblyName>
<PackageId>Markdig</PackageId>
<PackageId Condition="'$(SignAssembly)' == 'true'">Markdig.Signed</PackageId>
<PackageTags>Markdown CommonMark md html md2html</PackageTags>
<PackageReleaseNotes>
&gt; 0.12.4
- Fix Abbreviation extension not behaving properly in some cases
- Make Profile328 (for sl50 compat) not using unsafe code to pass verifier (issue #131)
&gt; 0.13.4
- Add support for single table header row without a table body rows (#141)
- ADd support for `nomnoml` diagrams
&gt; 0.13.3
- Add support for Pandoc YAML frontmatter (#138)
&gt; 0.13.2
- Add support for UAP10.0 (#137)
&gt; 0.13.1
- Fix indenting issue after a double digit list block using a tab (#134)
&gt; 0.13.0
- Update to latest CommonMark specs 0.28
</PackageReleaseNotes>
<PackageIconUrl>https://raw.githubusercontent.com/lunet-io/markdig/master/img/markdig.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/lunet-io/markdig</PackageProjectUrl>
@@ -55,12 +63,20 @@
<DefineConstants>$(DefineConstants);NETSTANDARD_11;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition="'$(TargetPlatformVersion)' == ''">10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion Condition="'$(TargetPlatformMinVersion)' == ''">10.0.10240.0</TargetPlatformMinVersion>
<DefineConstants>$(DefineConstants);NETSTANDARD_11;SUPPORT_UNSAFE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'portable40-net40+sl5+win8+wp8+wpa81'">
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile328</TargetFrameworkProfile>
<LanguageTargets>$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets</LanguageTargets>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -69,5 +85,14 @@
<PropertyGroup Condition=" '$(SignAssembly)' == 'true' ">
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
</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

@@ -274,20 +274,6 @@ namespace Markdig.Parsers.Inlines
var embracer = (ContainerInline)openDelimiter;
// Go down to the first emphasis with a lower level
while (true)
{
var previousEmphasis = embracer.FirstChild as EmphasisInline;
if (previousEmphasis != null && previousEmphasis.IsDouble && !isStrong && embracer.FirstChild == embracer.LastChild)
{
embracer = previousEmphasis;
}
else
{
break;
}
}
// Copy attributes attached to delimiter to the emphasis
var attributes = closeDelimiter.TryGetAttributes();
if (attributes != null)

View File

@@ -230,17 +230,16 @@ namespace Markdig.Parsers
return BlockState.None;
}
// We require at least one char
state.NextColumn();
// Parse the following indent
state.RestartIndent();
var columnBeforeIndent = state.Column;
state.ParseIndent();
if (state.IsCodeIndent)
// We expect at most 4 columns after
// If we have more, we reset the position
if (state.Indent > 4)
{
state.GoToColumn(columnBeforeIndent);
state.GoToColumn(columnBeforeIndent + 1);
}
// Number of spaces required for the following content to be part of this list item

View File

@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{061866E2-005C-4D13-A338-EA464BBEC60F}"
ProjectSection(SolutionItems) = preProject
@@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdig.WebApp", "Markdig.W
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnicodeNormDApp", "UnicodeNormDApp\UnicodeNormDApp.csproj", "{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdtoc", "mdtoc\mdtoc.csproj", "{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -52,8 +54,15 @@ Global
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33FFC0B9-0187-44F9-9424-BB5AF5B4FB84}.Release|Any CPU.Build.0 = Release|Any CPU
{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D068F7B6-6ACC-456C-A2E1-10EA746D956D}
EndGlobalSection
EndGlobal

6
src/mdtoc/App.config Normal file
View File

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

101
src/mdtoc/Program.cs Normal file
View File

@@ -0,0 +1,101 @@
// 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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using Markdig;
using Markdig.Extensions.AutoIdentifiers;
using Markdig.Renderers;
using Markdig.Renderers.Html;
using Markdig.Syntax;
namespace mdtoc
{
/// <summary>
/// A tool to generate a markdown TOC from a markdown local file or a github link to a markdown file.
/// </summary>
class Program
{
static void Error(string message)
{
Console.WriteLine(message);
Environment.Exit(1);
}
static void Main(string[] args)
{
if (args.Length != 1 || args[0] == "--help" || args[0] == "-help" || args[0] == "/?" || args[0] == "/help")
{
Error("Usage: mdtoc [markdown file path | http github URL]");
return;
}
var path = args[0];
string markdown = null;
if (path.StartsWith("https:"))
{
Uri uri;
if (!Uri.TryCreate(path, UriKind.Absolute, out uri))
{
Error($"Unable to parse Uri `{path}`");
return;
}
// Special handling of github URL to access the raw content instead
if (uri.Host == "github.com")
{
// https://github.com/lunet-io/scriban/blob/master/doc/language.md
// https://raw.githubusercontent.com/lunet-io/scriban/master/doc/language.md
var newPath = uri.AbsolutePath;
var paths = new List<string>(newPath.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries));
if (paths.Count < 5 || paths[2] != "blob")
{
Error($"Invalid github.com URL `{path}`");
return;
}
paths.RemoveAt(2); // remove blob
uri = new Uri($"https://raw.githubusercontent.com/{(string.Join("/", paths))}");
}
var httpClient = new HttpClient();
markdown = httpClient.GetStringAsync(uri).ConfigureAwait(false).GetAwaiter().GetResult();
}
else
{
markdown = File.ReadAllText(path);
}
var pipeline = new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub).Build();
var doc = Markdown.Parse(markdown, pipeline);
// Precomputes the minHeading
var headings = doc.Descendants<HeadingBlock>().ToList();
int minHeading = int.MaxValue;
int maxHeading = int.MinValue;
foreach (var heading in headings)
{
minHeading = Math.Min(minHeading, heading.Level);
maxHeading = Math.Max(maxHeading, heading.Level);
}
var writer = Console.Out;
// Use this htmlWriter to write content of headings into link label
var htmlWriter = new HtmlRenderer(writer) {EnableHtmlForInline = true};
foreach (var heading in headings)
{
var indent = heading.Level - minHeading;
for (int i = 0; i < indent; i++)
{
// - Start Of Heading
writer.Write(" ");
}
writer.Write("- [");
htmlWriter.WriteLeafInline(heading);
writer.Write($"](#{heading.GetAttributes().Id})");
writer.WriteLine();
}
}
}
}

View File

@@ -0,0 +1,39 @@
// 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.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("mdtoc")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Alexandre Mutel")]
[assembly: AssemblyProduct("mdtoc")]
[assembly: AssemblyCopyright("Copyright © 2017 - Alexandre Mutel")]
[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("e3cdff0f-5bfc-42e9-bdba-2797651900a2")]
// 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")]

58
src/mdtoc/mdtoc.csproj Normal file
View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E3CDFF0F-5BFC-42E9-BDBA-2797651900A2}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>mdtoc</RootNamespace>
<AssemblyName>mdtoc</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<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' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<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="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Markdig\Markdig.csproj">
<Project>{8a58a7e2-627c-4f41-933f-5ac92adfab48}</Project>
<Name>Markdig</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>