diff --git a/src/Textamina.Markdig/Parsers/BlockParser.cs b/src/Textamina.Markdig/Parsers/BlockParser.cs index 13a19b70..c9abf665 100644 --- a/src/Textamina.Markdig/Parsers/BlockParser.cs +++ b/src/Textamina.Markdig/Parsers/BlockParser.cs @@ -2,14 +2,12 @@ using Textamina.Markdig.Syntax; namespace Textamina.Markdig.Parsers { - public abstract class BlockParser : IBlockParser + public abstract class BlockParser : ParserBase, IBlockParser { protected BlockParser() { } - public char[] OpeningCharacters { get; protected set; } - public bool HasOpeningCharacter(char c) { if (OpeningCharacters != null) diff --git a/src/Textamina.Markdig/Parsers/BlockParserList.cs b/src/Textamina.Markdig/Parsers/BlockParserList.cs new file mode 100644 index 00000000..5dab26a5 --- /dev/null +++ b/src/Textamina.Markdig/Parsers/BlockParserList.cs @@ -0,0 +1,7 @@ +namespace Textamina.Markdig.Parsers +{ + public class BlockParserList : ParserList + { + + } +} \ No newline at end of file diff --git a/src/Textamina.Markdig/Parsers/BlockParserState.cs b/src/Textamina.Markdig/Parsers/BlockParserState.cs index c8283873..83411c2a 100644 --- a/src/Textamina.Markdig/Parsers/BlockParserState.cs +++ b/src/Textamina.Markdig/Parsers/BlockParserState.cs @@ -8,10 +8,9 @@ namespace Textamina.Markdig.Parsers { public class BlockParserState { - private readonly ParserList blockParsers; private int currentStackIndex; - public BlockParserState(StringBuilderCache stringBuilders, Document root, ParserList parsers) + public BlockParserState(StringBuilderCache stringBuilders, Document root, BlockParserList parsers) { if (stringBuilders == null) throw new ArgumentNullException(nameof(stringBuilders)); if (root == null) throw new ArgumentNullException(nameof(root)); @@ -21,13 +20,15 @@ namespace Textamina.Markdig.Parsers NewBlocks = new Stack(); root.IsOpen = true; Stack = new List {root}; - blockParsers = parsers; + Parsers = parsers; } public List Stack { get; } public Stack NewBlocks { get; } + public BlockParserList Parsers { get; } + public ContainerBlock CurrentContainer { get; private set; } public Block LastBlock { get; private set; } @@ -412,8 +413,8 @@ namespace Textamina.Markdig.Parsers // Eat indent spaces before checking the character ParseIndent(); - var parsers = blockParsers.GetParsersForOpeningCharacter(CurrentChar); - var globalParsers = blockParsers.GlobalParsers; + var parsers = Parsers.GetParsersForOpeningCharacter(CurrentChar); + var globalParsers = Parsers.GlobalParsers; if (parsers != null) { diff --git a/src/Textamina.Markdig/Parsers/IBlockParser.cs b/src/Textamina.Markdig/Parsers/IBlockParser.cs index 685f23c7..1c5f666b 100644 --- a/src/Textamina.Markdig/Parsers/IBlockParser.cs +++ b/src/Textamina.Markdig/Parsers/IBlockParser.cs @@ -5,6 +5,8 @@ namespace Textamina.Markdig.Parsers public interface ICharacterParser { char[] OpeningCharacters { get; } + + int Index { get; } } public interface IBlockParser : ICharacterParser diff --git a/src/Textamina.Markdig/Parsers/InlineParser.cs b/src/Textamina.Markdig/Parsers/InlineParser.cs index 17150c84..efe22288 100644 --- a/src/Textamina.Markdig/Parsers/InlineParser.cs +++ b/src/Textamina.Markdig/Parsers/InlineParser.cs @@ -2,12 +2,18 @@ using Textamina.Markdig.Syntax; namespace Textamina.Markdig.Parsers { - public abstract class InlineParser : ICharacterParser + public class ParserBase : ICharacterParser + { + public char[] OpeningCharacters { get; protected set; } + + public int Index { get; internal set; } + } + + + public abstract class InlineParser : ParserBase { public delegate void CloseBlockDelegate(InlineParserState state); - public char[] OpeningCharacters { get; protected set; } - public abstract bool Match(InlineParserState state, ref StringSlice slice); public CloseBlockDelegate OnCloseBlock { get; set; } diff --git a/src/Textamina.Markdig/Parsers/InlineParserList.cs b/src/Textamina.Markdig/Parsers/InlineParserList.cs new file mode 100644 index 00000000..3cefa65a --- /dev/null +++ b/src/Textamina.Markdig/Parsers/InlineParserList.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Textamina.Markdig.Parsers +{ + public class InlineParserList : ParserList + { + public InlineParserList() + { + } + + public InlineParser[] ClosingParsers { get; private set; } + + public override void Initialize() + { + base.Initialize(); + + var closingParsers = new InlineParserList(); + foreach (var parser in this) + { + if (parser.OnCloseBlock != null) + { + closingParsers.Add(parser); + } + } + + ClosingParsers = closingParsers.ToArray(); + } + } +} \ No newline at end of file diff --git a/src/Textamina.Markdig/Parsers/InlineParserState.cs b/src/Textamina.Markdig/Parsers/InlineParserState.cs index 3b436983..edb8f649 100644 --- a/src/Textamina.Markdig/Parsers/InlineParserState.cs +++ b/src/Textamina.Markdig/Parsers/InlineParserState.cs @@ -10,7 +10,7 @@ namespace Textamina.Markdig.Parsers { public class InlineParserState { - public InlineParserState(StringBuilderCache stringBuilders, Document document, ParserList parsers) + public InlineParserState(StringBuilderCache stringBuilders, Document document, InlineParserList parsers) { if (stringBuilders == null) throw new ArgumentNullException(nameof(stringBuilders)); if (document == null) throw new ArgumentNullException(nameof(document)); @@ -30,7 +30,7 @@ namespace Textamina.Markdig.Parsers public readonly List InlinesToClose; - public readonly ParserList Parsers; + public readonly InlineParserList Parsers; public readonly Document Document; diff --git a/src/Textamina.Markdig/Parsers/MarkdownParser.cs b/src/Textamina.Markdig/Parsers/MarkdownParser.cs index 6cf3954e..fa5dfc41 100644 --- a/src/Textamina.Markdig/Parsers/MarkdownParser.cs +++ b/src/Textamina.Markdig/Parsers/MarkdownParser.cs @@ -15,7 +15,7 @@ namespace Textamina.Markdig.Parsers private readonly BlockParserState blockParserState; private readonly StringBuilderCache stringBuilderCache; private readonly InlineParserState inlineState; - private readonly ParserList inlineParsers; + private readonly InlineParserList inlineParsers; public MarkdownParser(TextReader reader) { @@ -24,7 +24,7 @@ namespace Textamina.Markdig.Parsers stringBuilderCache = new StringBuilderCache(); // TODO: Make this configurable outside here - var blockParsers = new ParserList() + var blockParsers = new BlockParserList() { new ThematicBreakParser(), new HeadingBlockParser(), @@ -38,7 +38,7 @@ namespace Textamina.Markdig.Parsers }; blockParsers.Initialize(); - inlineParsers = new ParserList() + inlineParsers = new InlineParserList() { new HtmlEntityParser(), new LinkInlineParser(), diff --git a/src/Textamina.Markdig/Parsers/ParserList.cs b/src/Textamina.Markdig/Parsers/ParserList.cs index 10842b19..0d113676 100644 --- a/src/Textamina.Markdig/Parsers/ParserList.cs +++ b/src/Textamina.Markdig/Parsers/ParserList.cs @@ -6,7 +6,7 @@ using Textamina.Markdig.Helpers; namespace Textamina.Markdig.Parsers { - public class ParserList : List where T : class, ICharacterParser + public abstract class ParserList : List where T : ParserBase { private T[][] parsersWithOpeningCharacters; private T[] globalParsers; @@ -36,17 +36,24 @@ namespace Textamina.Markdig.Parsers return -1; } - public void Initialize() + public virtual void Initialize() { var charCounter = new Dictionary(); int globalCounter = 0; int maxChar = 0; - foreach (var parser in this) + for (int i = 0; i < this.Count; i++) { + var parser = this[i]; + parser.Index = i; if (parser.OpeningCharacters != null && parser.OpeningCharacters.Length != 0) { foreach (var openingChar in parser.OpeningCharacters) { + if (openingChar >= 127) + { + throw new InvalidOperationException($"Invalid non-ascii character `{openingChar}` used by the parser [{parser.GetType().Name}]. Only ASCII < 127 are allowed"); + } + if (!charCounter.ContainsKey(openingChar)) { charCounter[openingChar] = 0; diff --git a/src/Textamina.Markdig/Textamina.Markdig.csproj b/src/Textamina.Markdig/Textamina.Markdig.csproj index 878f940e..d2b94d2c 100644 --- a/src/Textamina.Markdig/Textamina.Markdig.csproj +++ b/src/Textamina.Markdig/Textamina.Markdig.csproj @@ -41,8 +41,10 @@ + +