using Markdig.Parsers.Inlines; using Markdig.Renderers; using Markdig.Renderers.Html; using Markdig.Syntax.Inlines; using NUnit.Framework; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace Markdig.Tests { [TestFixture] public class TestEmphasisExtended { class EmphasisTestExtension : IMarkdownExtension { public void Setup(MarkdownPipelineBuilder pipeline) { var emphasisParser = pipeline.InlineParsers.Find(); Debug.Assert(emphasisParser != null); foreach (var emphasis in EmphasisTestDescriptors) { emphasisParser.EmphasisDescriptors.Add( new EmphasisDescriptor(emphasis.Character, emphasis.Minimum, emphasis.Maximum, true)); } emphasisParser.TryCreateEmphasisInlineList.Add((delimiterChar, delimiterCount) => { return delimiterChar == '*' || delimiterChar == '_' ? null : new CustomEmphasisInline() { DelimiterChar = delimiterChar, DelimiterCount = delimiterCount }; }); } public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) { renderer.ObjectRenderers.Insert(0, new EmphasisRenderer()); } class EmphasisRenderer : HtmlObjectRenderer { protected override void Write(HtmlRenderer renderer, CustomEmphasisInline obj) { var tag = EmphasisTestDescriptors.First(test => test.Character == obj.DelimiterChar).Tags[obj.DelimiterCount]; renderer.Write(tag.OpeningTag); renderer.WriteChildren(obj); renderer.Write(tag.ClosingTag); } } } class Tag { #pragma warning disable CS0649 public int Level; #pragma warning restore CS0649 public string RawTag; public string OpeningTag; public string ClosingTag; public Tag(string tag) { RawTag = tag; OpeningTag = "<" + tag + ">"; ClosingTag = ""; } public static implicit operator Tag(string tag) => new Tag(tag); } class EmphasisTestDescriptor { public char Character; public int Minimum; public int Maximum; public Dictionary Tags = new Dictionary(); private EmphasisTestDescriptor(char character, int min, int max) { Character = character; Minimum = min; Maximum = max; } public EmphasisTestDescriptor(char character, int min, int max, params Tag[] tags) : this(character, min, max) { Debug.Assert(tags.Length == max - min + 1); foreach (var tag in tags) { Tags.Add(min++, tag); } } public EmphasisTestDescriptor(char character, int min, int max, string tag) : this(character, min, max, new Tag(tag)) { } } class CustomEmphasisInline : EmphasisInline { } static readonly EmphasisTestDescriptor[] EmphasisTestDescriptors = new[] { // Min Max new EmphasisTestDescriptor('"', 1, 1, "quotation"), new EmphasisTestDescriptor(',', 1, 2, "comma", "extra-comma"), new EmphasisTestDescriptor('!', 2, 3, "warning", "error"), new EmphasisTestDescriptor('=', 1, 3, "equal", "really-equal", "congruent"), new EmphasisTestDescriptor('1', 1, 1, "one-only"), new EmphasisTestDescriptor('2', 2, 2, "two-only"), new EmphasisTestDescriptor('3', 3, 3, "three-only"), }; static readonly MarkdownPipeline Pipeline = new MarkdownPipelineBuilder().Use().Build(); [Test] [TestCase("*foo**", "foo*")] [TestCase("**foo*", "*foo")] [TestCase("***foo***", "foo")] [TestCase("**_foo_**", "foo")] [TestCase("_**foo**_", "foo")] [TestCase("\"foo\"", "foo")] [TestCase("\"\"foo\"\"", "foo")] [TestCase("\"foo\"\"", "foo"")] [TestCase("\"\"foo\"", ""foo")] [TestCase(", foo", ", foo")] [TestCase(", foo,", ", foo,")] [TestCase(",some, foo,", "some foo,")] [TestCase(",,foo,,", "foo")] [TestCase(",foo,,", "foo,")] [TestCase(",,,foo,,,", "foo")] [TestCase("!1!", "!1!")] [TestCase("!!2!!", "2")] [TestCase("!!!3!!!", "3")] [TestCase("!!!34!!!!", "34!")] [TestCase("!!!!43!!!", "!43")] [TestCase("!!!!44!!!!", "!44!")] // This is a new case - should the second ! be before or after ? [TestCase("!!!!!5!!!!!", "5")] [TestCase("!!!!!!6!!!!!!", "6")] [TestCase("!! !mixed!!!", "!! !mixed!!!")] // can't open the delimiter because of the whitespace [TestCase("=", "=")] [TestCase("==", "==")] [TestCase("====", "====")] [TestCase("=a", "=a")] [TestCase("=a=", "a")] [TestCase("==a=", "=a")] [TestCase("==a==", "a")] [TestCase("==a===", "a=")] [TestCase("===a===", "a")] [TestCase("====a====", "a")] [TestCase("=====a=====", "a")] [TestCase("1", "1")] [TestCase("1 1", "1 1")] [TestCase("1Foo1", "Foo")] [TestCase("1121", "12")] [TestCase("22322", "3")] [TestCase("2232", "2232")] [TestCase("333", "333")] [TestCase("3334333", "4")] [TestCase("33334333", "34")] [TestCase("33343333", "43")] [TestCase("122122", "2222")] [TestCase("221221", "11")] [TestCase("122foo221", "foo")] [TestCase("122foo122", "22foo22")] [TestCase("!!!!!Attention:!! \"==1+1== 2\",but ===333 and 222===, mod 111!!!", "Attention: + 2but 333 and 222 mod 111")] public void TestEmphasis(string markdown, string expectedHtml) { TestParser.TestSpec(markdown, "

" + expectedHtml + "

", Pipeline); } } }