Skip to content

Commit

Permalink
Merge pull request #62 from whistyun/fix_bug
Browse files Browse the repository at this point in the history
Fix bug
  • Loading branch information
whistyun authored Nov 11, 2021
2 parents 604b739 + 65d8b20 commit 3fb2cda
Show file tree
Hide file tree
Showing 13 changed files with 552 additions and 86 deletions.
2 changes: 1 addition & 1 deletion Markdown.Avalonia.props
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</PropertyGroup>

<PropertyGroup>
<PackageVersion>0.10.7</PackageVersion>
<PackageVersion>0.10.8</PackageVersion>
</PropertyGroup>

</Project>
Expand Down
32 changes: 32 additions & 0 deletions Markdown.Avalonia/ContainerSwitcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Metadata;
using Markdown.Avalonia.Utils;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Markdown.Avalonia
{
public class ContainerSwitch : AvaloniaDictionary<string, IContainerBlockHandler>, IContainerBlockHandler
{
public Border ProvideControl(string assetPathRoot, string blockName, string lines)
{
// blockName may be "name [title] (url) {option}".
// This collect some character until "[", "(" or "{".
var trimedBlockName = blockName.Trim();
var match = Regex.Match(trimedBlockName, @"[\(\[\{]");
if (match.Success)
{
trimedBlockName = trimedBlockName.Substring(0, match.Index).Trim();
}

if (this.TryGetValue(trimedBlockName, out var processor))
{
return processor.ProvideControl(assetPathRoot, blockName, lines);
}
else return null;
}
}
}
185 changes: 102 additions & 83 deletions Markdown.Avalonia/Markdown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class Markdown : AvaloniaObject, IMarkdownEngine
public const string Heading6Class = "Heading6";

public const string CodeBlockClass = "CodeBlock";
public const string ContainerBlockClass = "ContainerBlock";
public const string NoContainerClass = "NoContainer";
public const string BlockquoteClass = "Blockquote";
public const string NoteClass = "Note";

Expand Down Expand Up @@ -155,18 +157,20 @@ private IEnumerable<Control> RunBlockGamut(string text, bool supportTextAlignmen
Helper.ThrowArgNull(nameof(text));
}

return Evaluate2(
return Evaluates(
text,
_codeBlockFirst, CodeBlocksWithLangEvaluator,
_listLevel > 0 ? _listNested : _listTopLevel, ListEvaluator,
s1 => DoContainerBlock(s1,
s2 => DoBlockquotes(s2,
s3 => DoHeaders(s3,
s4 => DoHorizontalRules(s4,
s5 => DoTable(s5,
s6 => DoNote(s6, supportTextAlignment,
s7 => DoIndentCodeBlock(s7,
sn => FormParagraphs(sn, supportTextAlignment))))))) )
new[] {
Parser.Create<Control>(_codeBlockFirst, CodeBlocksWithLangEvaluator),
Parser.Create<Control>(_containerBlockFirst, ContainerBlockEvaluator),
Parser.Create<Control>(_listLevel > 0 ? _listNested : _listTopLevel, ListEvaluator),
},
s1 => DoBlockquotes(s1,
s2 => DoHeaders(s2,
s3 => DoHorizontalRules(s3,
s4 => DoTable(s4,
s5 => DoNote(s5, supportTextAlignment,
s6 => DoIndentCodeBlock(s6,
sn => FormParagraphs(sn, supportTextAlignment)))))))
);
}

Expand Down Expand Up @@ -1082,40 +1086,28 @@ private IEnumerable<Border> CreateTableRow(IList<ITableCell> mdcells, int rowIdx
\1
(?!:)[\n]+", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline | RegexOptions.Compiled);


private IEnumerable<Control> DoContainerBlock(string text, Func<string, IEnumerable<Control>> defaultHandler)
{
if (text is null)
{
Helper.ThrowArgNull(nameof(text));
}

return Evaluate(
text, _containerBlockFirst, ContainerBlockEvaluator,
sn => Evaluate(sn, _containerBlockFirst, ContainerBlockEvaluator, defaultHandler)
);
}

private Border ContainerBlockEvaluator(Match match)
{
if ( match is null )
if (match is null)
{
Helper.ThrowArgNull(nameof(match));
}

if( ContainerBlockHandler == null )
{
Border _retVal = CodeBlocksEvaluator( null, match.Value );
_retVal.BorderBrush = Brushes.Red;
var result = ContainerBlockHandler?.ProvideControl(AssetPathRoot, match.Groups[2].Value, match.Groups[3].Value);

if (result == null)
{
Border _retVal = CodeBlocksEvaluator(null, match.Value);
_retVal.Classes.Add(NoContainerClass);
return _retVal;
}

return ContainerBlockHandler?.ProvideControl( AssetPathRoot, match.Groups[2].Value, match.Groups[3].Value );

result.Classes.Add(ContainerBlockClass);
return result;
}

#endregion

#region grammer - code block

private static Regex _codeBlockFirst = new Regex(@"
Expand Down Expand Up @@ -1831,75 +1823,49 @@ private TResult Create<TResult, TContent>(IEnumerable<TContent> content)

return result;
}
private IEnumerable<T> Evaluate2<T>(

private IEnumerable<T> Evaluates<T>(
string text,
Regex expression1, Func<Match, T> build1,
Regex expression2, Func<Match, IEnumerable<T>> build2,
Func<string, IEnumerable<T>> rest)
Parser<T>[] parsers,
Func<string, IEnumerable<T>> rest
)
{
if (text is null)
{
Helper.ThrowArgNull(nameof(text));
}

var index = 0;

var rtn = new List<T>();

var match1 = expression1.Match(text, index);
var match2 = expression2.Match(text, index);

IEnumerable<T> ProcPre(Match m)
while (true)
{
var prefix = text.Substring(index, m.Index - index);
return rest(prefix);
}
int bestIndex = Int32.MaxValue;
Match bestMatch = null;
Parser<T> bestParser = null;

void ProcessMatch1()
{
if (match1.Index > index)
foreach (var parser in parsers)
{
rtn.AddRange(ProcPre(match1));
var match = parser.Match(text, index);
if (match.Success && match.Index < bestIndex)
{
bestIndex = match.Index;
bestMatch = match;
bestParser = parser;
}
}
rtn.Add(build1(match1));
index = match1.Index + match1.Length;
}

void ProcessMatch2()
{
if (match2.Index > index)
{
rtn.AddRange(ProcPre(match2));
}
rtn.AddRange(build2(match2));
index = match2.Index + match2.Length;
}
if (bestParser == null) break;

// match1 vs match2
while (match1.Success && match2.Success)
{
if (match1.Index < match2.Index)
{
ProcessMatch1();
}
else
if (bestIndex > index)
{
ProcessMatch2();
var prefix = text.Substring(index, bestIndex - index);
rtn.AddRange(rest(prefix));
}
match1 = expression1.Match(text, index);
match2 = expression2.Match(text, index);
}

while (match1.Success)
{
ProcessMatch1();
match1 = expression1.Match(text, index);
}
rtn.AddRange(bestParser.Convert(bestMatch));

while (match2.Success)
{
ProcessMatch2();
match2 = expression2.Match(text, index);
index = bestIndex + bestMatch.Length;
}

if (index < text.Length)
Expand All @@ -1909,6 +1875,7 @@ void ProcessMatch2()
}

return rtn;

}

private IEnumerable<T> Evaluate<T>(string text, Regex expression, Func<Match, T> build, Func<string, IEnumerable<T>> rest)
Expand Down Expand Up @@ -1947,5 +1914,57 @@ private IEnumerable<T> Evaluate<T>(string text, Regex expression, Func<Match, T>
}

#endregion

static class Parser
{
public static Parser<T> Create<T>(Regex pattern, Func<Match, T> converter)
=> new SingleParser<T>(pattern, converter);

public static Parser<T> Create<T>(Regex pattern, Func<Match, IEnumerable<T>> converter)
=> new MultiParser<T>(pattern, converter);
}

abstract class Parser<T>
{
private Regex pattern;

public Parser(Regex pattern)
{
this.pattern = pattern;
}

public Match Match(string text, int index) => pattern.Match(text, index);

public abstract IEnumerable<T> Convert(Match match);
}

class SingleParser<T> : Parser<T>
{
private Func<Match, T> converter;

public SingleParser(Regex pattern, Func<Match, T> converter) : base(pattern)
{
this.converter = converter;
}

public override IEnumerable<T> Convert(Match match)
{
yield return converter(match);
}
}

class MultiParser<T> : Parser<T>
{
private Func<Match, IEnumerable<T>> converter;

public MultiParser(Regex pattern, Func<Match, IEnumerable<T>> converter) : base(pattern)
{
this.converter = converter;
}

public override IEnumerable<T> Convert(Match match) => converter(match);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
<Setter Property="Foreground" Value="{mde:DivideColor Blue, ThemeForegroundColor, 0.45}"/>
</Style.Setters>
</Style>
<Style Selector="Border.NoContainer">
<Style.Setters>
<Setter Property="BorderBrush" Value="Red"/>
</Style.Setters>
</Style>

<Style Selector="ctxt|CCode">
<Style.Setters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
<Setter Property="Foreground" Value="{mde:DivideColor Blue, SystemBaseHighColor, 0.45}"/>
</Style.Setters>
</Style>
<Style Selector="Border.NoContainer">
<Style.Setters>
<Setter Property="BorderBrush" Value="Red"/>
</Style.Setters>
</Style>

<Style Selector="ctxt|CCode">
<Style.Setters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@
<Setter Property="Foreground" Value="DarkBlue"/>
</Style.Setters>
</Style>
<Style Selector="Border.NoContainer">
<Style.Setters>
<Setter Property="BorderBrush" Value="Red"/>
</Style.Setters>
</Style>

<Style Selector="Border.Note">
<Style.Setters>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
<Setter Property="Foreground" Value="DarkBlue"/>
</Style.Setters>
</Style>
<Style Selector="Border.NoContainer">
<Style.Setters>
<Setter Property="BorderBrush" Value="Red"/>
</Style.Setters>
</Style>

<Style Selector="ctxt|CCode">
<Style.Setters>
Expand Down
Loading

0 comments on commit 3fb2cda

Please sign in to comment.