| @@ -324,9 +324,9 @@ img { | |||
| border: 0; | |||
| -ms-interpolation-mode: bicubic; | |||
| vertical-align: middle; | |||
| box-shadow: 0px 0px 10px rgba(10,10,10,0.3); | |||
| } | |||
| input { | |||
| line-height: normal; | |||
| font-size: 100%; | |||
| @@ -476,8 +476,9 @@ div.figure { | |||
| text-align: center; | |||
| } | |||
| div.figure img { | |||
| img.shadowed, div.figure img { | |||
| margin: 0 auto; | |||
| box-shadow: 0px 0px 10px rgba(10,10,10,0.3); | |||
| } | |||
| div.figure p { | |||
| @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; | |||
| // 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("0.9.2.0")] | |||
| [assembly: AssemblyFileVersion("0.9.2")] | |||
| [assembly: AssemblyVersion("0.10.0.0")] | |||
| [assembly: AssemblyFileVersion("0.10.0")] | |||
| @@ -21,54 +21,33 @@ namespace MarkdownDeep | |||
| { | |||
| public class LinkDefinition | |||
| { | |||
| public LinkDefinition(string id) | |||
| public LinkDefinition(string id) : this(id, string.Empty, string.Empty) | |||
| { | |||
| this.id= id; | |||
| } | |||
| public LinkDefinition(string id, string url) | |||
| public LinkDefinition(string id, string url) : this(id, url, string.Empty) | |||
| { | |||
| this.id = id; | |||
| this.url = url; | |||
| } | |||
| public LinkDefinition(string id, string url, string title) | |||
| { | |||
| this.id = id; | |||
| this.url = url; | |||
| this.title = title; | |||
| } | |||
| public string id | |||
| { | |||
| get; | |||
| set; | |||
| } | |||
| public string url | |||
| { | |||
| get; | |||
| set; | |||
| } | |||
| public string title | |||
| { | |||
| get; | |||
| set; | |||
| this.Id = id; | |||
| this.Url = url; | |||
| this.Title = title; | |||
| } | |||
| internal void RenderLink(Markdown m, StringBuilder b, string link_text) | |||
| internal void RenderLink(Markdown m, StringBuilder b, string link_text, List<string> specialAttributes) | |||
| { | |||
| if (url.StartsWith("mailto:")) | |||
| if (this.Url.StartsWith("mailto:")) | |||
| { | |||
| b.Append("<a href=\""); | |||
| Utils.HtmlRandomize(b, url); | |||
| Utils.HtmlRandomize(b, this.Url); | |||
| b.Append('\"'); | |||
| if (!String.IsNullOrEmpty(title)) | |||
| if (!String.IsNullOrEmpty(this.Title)) | |||
| { | |||
| b.Append(" title=\""); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(b, title); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(b, this.Title); | |||
| b.Append('\"'); | |||
| } | |||
| b.Append('>'); | |||
| @@ -81,17 +60,22 @@ namespace MarkdownDeep | |||
| // encode url | |||
| StringBuilder sb = m.GetStringBuilder(); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Url); | |||
| tag.attributes["href"] = sb.ToString(); | |||
| // encode title | |||
| if (!String.IsNullOrEmpty(title )) | |||
| if (!String.IsNullOrEmpty(this.Title )) | |||
| { | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Title); | |||
| tag.attributes["title"] = sb.ToString(); | |||
| } | |||
| if(specialAttributes.Any()) | |||
| { | |||
| LinkDefinition.HandleSpecialAttributes(specialAttributes, sb, tag); | |||
| } | |||
| // Do user processing | |||
| m.OnPrepareLink(tag); | |||
| @@ -103,13 +87,14 @@ namespace MarkdownDeep | |||
| } | |||
| } | |||
| internal void RenderImg(Markdown m, StringBuilder b, string alt_text) | |||
| internal void RenderImg(Markdown m, StringBuilder b, string alt_text, List<string> specialAttributes) | |||
| { | |||
| HtmlTag tag = new HtmlTag("img"); | |||
| // encode url | |||
| StringBuilder sb = m.GetStringBuilder(); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, Url); | |||
| tag.attributes["src"] = sb.ToString(); | |||
| // encode alt text | |||
| @@ -121,13 +106,16 @@ namespace MarkdownDeep | |||
| } | |||
| // encode title | |||
| if (!String.IsNullOrEmpty(title)) | |||
| if (!String.IsNullOrEmpty(Title)) | |||
| { | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, Title); | |||
| tag.attributes["title"] = sb.ToString(); | |||
| } | |||
| if(specialAttributes.Any()) | |||
| { | |||
| LinkDefinition.HandleSpecialAttributes(specialAttributes, sb, tag); | |||
| } | |||
| tag.closed = true; | |||
| m.OnPrepareImage(tag, m.RenderingTitledImage); | |||
| @@ -220,7 +208,7 @@ namespace MarkdownDeep | |||
| return null; | |||
| // Unescape it | |||
| r.url = Utils.UnescapeString(url.Trim(), ExtraMode); | |||
| r.Url = Utils.UnescapeString(url.Trim(), ExtraMode); | |||
| } | |||
| else | |||
| { | |||
| @@ -247,7 +235,7 @@ namespace MarkdownDeep | |||
| p.SkipEscapableChar(ExtraMode); | |||
| } | |||
| r.url = Utils.UnescapeString(p.Extract().Trim(), ExtraMode); | |||
| r.Url = Utils.UnescapeString(p.Extract().Trim(), ExtraMode); | |||
| } | |||
| p.SkipLinespace(); | |||
| @@ -329,7 +317,7 @@ namespace MarkdownDeep | |||
| } | |||
| // Store the title | |||
| r.title = Utils.UnescapeString(p.Extract(), ExtraMode); | |||
| r.Title = Utils.UnescapeString(p.Extract(), ExtraMode); | |||
| // Skip closing quote | |||
| p.SkipForward(1); | |||
| @@ -337,5 +325,49 @@ namespace MarkdownDeep | |||
| // Done! | |||
| return r; | |||
| } | |||
| private static void HandleSpecialAttributes(List<string> specialAttributes, StringBuilder sb, HtmlTag tag) | |||
| { | |||
| string id = specialAttributes.FirstOrDefault(s => s.StartsWith("#")); | |||
| if(id != null && id.Length > 1) | |||
| { | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, id.Substring(1)); | |||
| tag.attributes["id"] = sb.ToString(); | |||
| } | |||
| var cssClasses = new List<string>(); | |||
| foreach(var cssClass in specialAttributes.Where(s => s.StartsWith(".") && s.Length > 1)) | |||
| { | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, cssClass.Substring(1)); | |||
| cssClasses.Add(sb.ToString()); | |||
| } | |||
| if(cssClasses.Any()) | |||
| { | |||
| tag.attributes["class"] = string.Join(" ", cssClasses.ToArray()); | |||
| } | |||
| foreach(var nameValuePair in specialAttributes.Where(s => s.Contains("=") && s.Length > 2 && !s.StartsWith(".") && !s.StartsWith("#"))) | |||
| { | |||
| var pair = nameValuePair.Split('='); | |||
| if(pair.Length == 2) | |||
| { | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, pair[0]); | |||
| var key = sb.ToString(); | |||
| sb.Length = 0; | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, pair[1]); | |||
| var value = sb.ToString(); | |||
| tag.attributes[key] = value; | |||
| } | |||
| } | |||
| } | |||
| #region Properties | |||
| public string Id { get; set; } | |||
| public string Url { get; set; } | |||
| public string Title { get; set; } | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -21,14 +21,36 @@ namespace MarkdownDeep | |||
| { | |||
| internal class LinkInfo | |||
| { | |||
| public LinkInfo(LinkDefinition def, string link_text) | |||
| public LinkInfo(LinkDefinition def, string link_text, List<string> specialAttributes ) | |||
| { | |||
| this.def = def; | |||
| this.link_text = link_text; | |||
| this.Definition = def; | |||
| this.LinkText = link_text; | |||
| this.SpecialAttributes = new List<string>(); | |||
| if(specialAttributes != null) | |||
| { | |||
| this.SpecialAttributes.AddRange(specialAttributes); | |||
| } | |||
| } | |||
| public LinkDefinition def; | |||
| public string link_text; | |||
| public void RenderLink(Markdown m, StringBuilder sb) | |||
| { | |||
| var sf = new SpanFormatter(m); | |||
| sf.DisableLinks = true; | |||
| this.Definition.RenderLink(m, sb, sf.Format(this.LinkText), this.SpecialAttributes); | |||
| } | |||
| public void RenderImage(Markdown m, StringBuilder sb) | |||
| { | |||
| this.Definition.RenderImg(m, sb, this.LinkText, this.SpecialAttributes); | |||
| } | |||
| public LinkDefinition Definition { get; set; } | |||
| public string LinkText { get; set; } | |||
| public List<string> SpecialAttributes { get; private set; } | |||
| } | |||
| } | |||
| @@ -568,7 +568,7 @@ namespace MarkdownDeep | |||
| internal void AddLinkDefinition(LinkDefinition link) | |||
| { | |||
| // Store it | |||
| m_LinkDefinitions[link.id]=link; | |||
| m_LinkDefinitions[link.Id]=link; | |||
| } | |||
| internal void AddFootnote(Block footnote) | |||
| @@ -38,7 +38,7 @@ namespace MarkdownDeep | |||
| // If the image is a titled image and there's a class defined for titled images, we'll render it using special markup, otherwise we'll render | |||
| // the image as-is. | |||
| if (m_Tokens.Count == 1 && !string.IsNullOrWhiteSpace(m_Markdown.HtmlClassTitledImages) && m_Tokens[0].type == TokenType.img && | |||
| m_Tokens[0].data is LinkInfo && !string.IsNullOrWhiteSpace(((LinkInfo)m_Tokens[0].data).def.title)) | |||
| m_Tokens[0].data is LinkInfo && !string.IsNullOrWhiteSpace(((LinkInfo)m_Tokens[0].data).Definition.Title)) | |||
| { | |||
| // Grab the link info | |||
| LinkInfo li = (LinkInfo)m_Tokens[0].data; | |||
| @@ -55,10 +55,10 @@ namespace MarkdownDeep | |||
| dest.Append("\n"); | |||
| // Render the title | |||
| if (!String.IsNullOrEmpty(li.def.title)) | |||
| if (!String.IsNullOrEmpty(li.Definition.Title)) | |||
| { | |||
| dest.Append("<p>"); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(dest, li.def.title); | |||
| Utils.SmartHtmlEncodeAmpsAndAngles(dest, li.Definition.Title); | |||
| dest.Append("</p>\n"); | |||
| } | |||
| @@ -128,7 +128,7 @@ namespace MarkdownDeep | |||
| case TokenType.link: | |||
| LinkInfo li = (LinkInfo)t.data; | |||
| sb.Append(li.link_text); | |||
| sb.Append(li.LinkText); | |||
| break; | |||
| } | |||
| @@ -222,17 +222,14 @@ namespace MarkdownDeep | |||
| case TokenType.link: | |||
| { | |||
| LinkInfo li = (LinkInfo)t.data; | |||
| var sf = new SpanFormatter(m_Markdown); | |||
| sf.DisableLinks = true; | |||
| li.def.RenderLink(m_Markdown, sb, sf.Format(li.link_text)); | |||
| li.RenderLink(m_Markdown, sb); | |||
| break; | |||
| } | |||
| case TokenType.img: | |||
| { | |||
| LinkInfo li = (LinkInfo)t.data; | |||
| li.def.RenderImg(m_Markdown, sb, li.link_text); | |||
| li.RenderImage(m_Markdown, sb); | |||
| break; | |||
| } | |||
| @@ -312,14 +309,14 @@ namespace MarkdownDeep | |||
| case TokenType.link: | |||
| { | |||
| LinkInfo li = (LinkInfo)t.data; | |||
| sb.Append(li.link_text); | |||
| sb.Append(li.LinkText); | |||
| break; | |||
| } | |||
| case TokenType.img: | |||
| { | |||
| LinkInfo li = (LinkInfo)t.data; | |||
| sb.Append(li.link_text); | |||
| sb.Append(li.LinkText); | |||
| break; | |||
| } | |||
| @@ -922,11 +919,11 @@ namespace MarkdownDeep | |||
| url = "mailto:" + url; | |||
| } | |||
| li = new LinkInfo(new LinkDefinition("auto", url, null), link_text); | |||
| li = new LinkInfo(new LinkDefinition("auto", url, null), link_text, null); | |||
| } | |||
| else if (Utils.IsWebAddress(url)) | |||
| { | |||
| li=new LinkInfo(new LinkDefinition("auto", url, null), url); | |||
| li=new LinkInfo(new LinkDefinition("auto", url, null), url, null); | |||
| } | |||
| if (li!=null) | |||
| @@ -981,7 +978,7 @@ namespace MarkdownDeep | |||
| if (DisableLinks && token_type==TokenType.link) | |||
| return null; | |||
| bool ExtraMode = m_Markdown.ExtraMode; | |||
| bool extraMode = m_Markdown.ExtraMode; | |||
| // Find the closing square bracket, allowing for nesting, watching for | |||
| // escapable characters | |||
| @@ -1001,7 +998,7 @@ namespace MarkdownDeep | |||
| break; | |||
| } | |||
| this.SkipEscapableChar(ExtraMode); | |||
| this.SkipEscapableChar(extraMode); | |||
| } | |||
| // Quit if end | |||
| @@ -1009,7 +1006,7 @@ namespace MarkdownDeep | |||
| return null; | |||
| // Get the link text and unescape it | |||
| string link_text = Utils.UnescapeString(Extract(), ExtraMode); | |||
| string link_text = Utils.UnescapeString(Extract(), extraMode); | |||
| // The closing ']' | |||
| SkipForward(1); | |||
| @@ -1030,8 +1027,19 @@ namespace MarkdownDeep | |||
| if (!SkipChar(')')) | |||
| return null; | |||
| List<string> specialAttributes = null; | |||
| if(extraMode && DoesMatch('{')) | |||
| { | |||
| int end; | |||
| specialAttributes = Utils.StripSpecialAttributes(this.Input, this.Position, out end); | |||
| if(specialAttributes != null) | |||
| { | |||
| Position = end; | |||
| } | |||
| } | |||
| // Create the token | |||
| return CreateToken(token_type, new LinkInfo(link_def, link_text)); | |||
| return CreateToken(token_type, new LinkInfo(link_def, link_text, specialAttributes)); | |||
| } | |||
| // Optional space or tab | |||
| @@ -1091,8 +1099,9 @@ namespace MarkdownDeep | |||
| if (def == null) | |||
| return null; | |||
| // Create a token | |||
| return CreateToken(token_type, new LinkInfo(def, link_text)); | |||
| // Create a token. | |||
| // [FB]: Currently not supported: special attributes on reference links. | |||
| return CreateToken(token_type, new LinkInfo(def, link_text, null)); | |||
| } | |||
| // Process a ``` code span ``` | |||
| @@ -1175,7 +1184,7 @@ namespace MarkdownDeep | |||
| #endregion | |||
| Markdown m_Markdown; | |||
| private Markdown m_Markdown; | |||
| internal bool DisableLinks; | |||
| List<Token> m_Tokens=new List<Token>(); | |||
| } | |||
| @@ -486,6 +486,50 @@ namespace MarkdownDeep | |||
| return strID; | |||
| } | |||
| /// <summary> | |||
| /// Strips the special attributes specified at the location of start. Special attributes are a php markdown extension | |||
| /// and specified between {}. Attributes are separated with spaces. It recognizes the following attributes: | |||
| /// id, which start with a '#'. Only the first one is used | |||
| /// css classes, which start with a'.'. All specified are used | |||
| /// name=value pairs, which will end up as attributes on the element. | |||
| /// </summary> | |||
| /// <param name="str">The string we're scanning.</param> | |||
| /// <param name="start">The start (current) position.</param> | |||
| /// <param name="end">The end position. Is only valid if returned list contains at least one value.</param> | |||
| /// <returns>list of special attributes found, or null if none found or error in string format.</returns> | |||
| public static List<string> StripSpecialAttributes(string str, int start, out int end) | |||
| { | |||
| end = start; | |||
| var scanner = new StringScanner(str, start); | |||
| if(!scanner.DoesMatch('{')) | |||
| { | |||
| // not a start of a special attribute block | |||
| return null; | |||
| } | |||
| // first find the end of the block, | |||
| scanner.SkipForward(1); | |||
| var startOfAttributes = scanner.Position; | |||
| // first find the next EOL, as the closing } has to be on this line. | |||
| scanner.SkipToEol(); | |||
| var nextEolPos = scanner.Position; | |||
| scanner.Position = startOfAttributes; | |||
| scanner.Mark(); | |||
| if(!scanner.Find('}') || scanner.Position >= nextEolPos) | |||
| { | |||
| // not enclosed properly. | |||
| return null; | |||
| } | |||
| var attributesString = scanner.Extract(); | |||
| if(string.IsNullOrWhiteSpace(attributesString)) | |||
| { | |||
| return null; | |||
| } | |||
| // Position is on enclosing '}' (due to the Find('}'), so we have to skip 1 character | |||
| end = scanner.Position + 1; | |||
| return attributesString.Split(' ').Where(s=>!string.IsNullOrWhiteSpace(s)).ToList(); | |||
| } | |||
| public static bool IsUrlFullyQualified(string url) | |||
| { | |||
| return url.Contains("://") || url.StartsWith("mailto:"); | |||
| @@ -10,85 +10,104 @@ namespace MarkdownDeepTests | |||
| [TestFixture] | |||
| class LinkAndImgTests | |||
| { | |||
| SpanFormatter _formatter; | |||
| [SetUp] | |||
| public void SetUp() | |||
| { | |||
| m = new Markdown(); | |||
| m.AddLinkDefinition(new LinkDefinition("link1", "url.com", "title")); | |||
| m.AddLinkDefinition(new LinkDefinition("link2", "url.com")); | |||
| m.AddLinkDefinition(new LinkDefinition("img1", "url.com/image.png", "title")); | |||
| m.AddLinkDefinition(new LinkDefinition("img2", "url.com/image.png")); | |||
| _formatter = new SpanFormatter(GetSetupMarkdown()); | |||
| } | |||
| [Test] | |||
| public void InlineLinkWithoutTitleWithSpecialAttributes() | |||
| { | |||
| var m = GetSetupMarkdown(); | |||
| m.ExtraMode = true; | |||
| var s = new SpanFormatter(m); | |||
| Assert.AreEqual("pre <a href=\"url.com\" id=\"foo\" class=\"a b cl\" lang=\"nl\">link text</a> post", | |||
| s.Format("pre [link text](url.com){#foo .a .b .cl lang=nl} post")); | |||
| } | |||
| s = new SpanFormatter(m); | |||
| [Test] | |||
| public void InlineImgWithoutTitleWithSpecialAttributes() | |||
| { | |||
| var m = GetSetupMarkdown(); | |||
| m.ExtraMode = true; | |||
| var s = new SpanFormatter(m); | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" id=\"foo\" class=\"a b cl\" lang=\"nl\" /> post", | |||
| s.Format("pre {#foo .a .b .cl lang=nl} post")); | |||
| } | |||
| [Test] | |||
| public void ReferenceLinkWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\" title=\"title\">link text</a> post", | |||
| s.Format("pre [link text][link1] post")); | |||
| _formatter.Format("pre [link text][link1] post")); | |||
| } | |||
| [Test] | |||
| public void ReferenceLinkIdsAreCaseInsensitive() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\" title=\"title\">link text</a> post", | |||
| s.Format("pre [link text][LINK1] post")); | |||
| _formatter.Format("pre [link text][LINK1] post")); | |||
| } | |||
| [Test] | |||
| public void ImplicitReferenceLinkWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\">link2</a> post", | |||
| s.Format("pre [link2] post")); | |||
| _formatter.Format("pre [link2] post")); | |||
| Assert.AreEqual("pre <a href=\"url.com\">link2</a> post", | |||
| s.Format("pre [link2][] post")); | |||
| _formatter.Format("pre [link2][] post")); | |||
| } | |||
| [Test] | |||
| public void ImplicitReferenceLinkWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\" title=\"title\">link1</a> post", | |||
| s.Format("pre [link1] post")); | |||
| _formatter.Format("pre [link1] post")); | |||
| Assert.AreEqual("pre <a href=\"url.com\" title=\"title\">link1</a> post", | |||
| s.Format("pre [link1][] post")); | |||
| _formatter.Format("pre [link1][] post")); | |||
| } | |||
| [Test] | |||
| public void ReferenceLinkWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\">link text</a> post", | |||
| s.Format("pre [link text][link2] post")); | |||
| _formatter.Format("pre [link text][link2] post")); | |||
| } | |||
| [Test] | |||
| public void MissingReferenceLink() | |||
| { | |||
| Assert.AreEqual("pre [link text][missing] post", | |||
| s.Format("pre [link text][missing] post")); | |||
| _formatter.Format("pre [link text][missing] post")); | |||
| } | |||
| [Test] | |||
| public void InlineLinkWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\" title=\"title\">link text</a> post", | |||
| s.Format("pre [link text](url.com \"title\") post")); | |||
| _formatter.Format("pre [link text](url.com \"title\") post")); | |||
| } | |||
| [Test] | |||
| public void InlineLinkWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\">link text</a> post", | |||
| s.Format("pre [link text](url.com) post")); | |||
| _formatter.Format("pre [link text](url.com) post")); | |||
| } | |||
| [Test] | |||
| public void Boundaries() | |||
| { | |||
| Assert.AreEqual("<a href=\"url.com\">link text</a>", | |||
| s.Format("[link text](url.com)")); | |||
| _formatter.Format("[link text](url.com)")); | |||
| Assert.AreEqual("<a href=\"url.com\" title=\"title\">link text</a>", | |||
| s.Format("[link text][link1]")); | |||
| _formatter.Format("[link text][link1]")); | |||
| } | |||
| @@ -96,53 +115,53 @@ namespace MarkdownDeepTests | |||
| public void ReferenceImgWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" title=\"title\" /> post", | |||
| s.Format("pre ![alt text][img1] post")); | |||
| _formatter.Format("pre ![alt text][img1] post")); | |||
| } | |||
| [Test] | |||
| public void ImplicitReferenceImgWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"img2\" /> post", | |||
| s.Format("pre ![img2] post")); | |||
| _formatter.Format("pre ![img2] post")); | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"img2\" /> post", | |||
| s.Format("pre ![img2][] post")); | |||
| _formatter.Format("pre ![img2][] post")); | |||
| } | |||
| [Test] | |||
| public void ImplicitReferenceImgWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"img1\" title=\"title\" /> post", | |||
| s.Format("pre ![img1] post")); | |||
| _formatter.Format("pre ![img1] post")); | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"img1\" title=\"title\" /> post", | |||
| s.Format("pre ![img1][] post")); | |||
| _formatter.Format("pre ![img1][] post")); | |||
| } | |||
| [Test] | |||
| public void ReferenceImgWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" /> post", | |||
| s.Format("pre ![alt text][img2] post")); | |||
| _formatter.Format("pre ![alt text][img2] post")); | |||
| } | |||
| [Test] | |||
| public void MissingReferenceImg() | |||
| { | |||
| Assert.AreEqual("pre ![alt text][missing] post", | |||
| s.Format("pre ![alt text][missing] post")); | |||
| _formatter.Format("pre ![alt text][missing] post")); | |||
| } | |||
| [Test] | |||
| public void InlineImgWithTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" title=\"title\" /> post", | |||
| s.Format("pre  post")); | |||
| _formatter.Format("pre  post")); | |||
| } | |||
| [Test] | |||
| public void InlineImgWithoutTitle() | |||
| { | |||
| Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" /> post", | |||
| s.Format("pre  post")); | |||
| _formatter.Format("pre  post")); | |||
| } | |||
| @@ -150,10 +169,19 @@ namespace MarkdownDeepTests | |||
| public void ImageLink() | |||
| { | |||
| Assert.AreEqual("pre <a href=\"url.com\"><img src=\"url.com/image.png\" alt=\"alt text\" /></a> post", | |||
| s.Format("pre [](url.com) post")); | |||
| _formatter.Format("pre [](url.com) post")); | |||
| } | |||
| private Markdown GetSetupMarkdown() | |||
| { | |||
| var toReturn = new Markdown(); | |||
| toReturn.AddLinkDefinition(new LinkDefinition("link1", "url.com", "title")); | |||
| toReturn.AddLinkDefinition(new LinkDefinition("link2", "url.com")); | |||
| toReturn.AddLinkDefinition(new LinkDefinition("img1", "url.com/image.png", "title")); | |||
| toReturn.AddLinkDefinition(new LinkDefinition("img2", "url.com/image.png")); | |||
| return toReturn; | |||
| } | |||
| Markdown m; | |||
| SpanFormatter s; | |||
| } | |||
| } | |||
| @@ -23,9 +23,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "url.com"); | |||
| Assert.AreEqual(r.title, null); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "url.com"); | |||
| Assert.AreEqual(r.Title, string.Empty); | |||
| } | |||
| [Test] | |||
| @@ -35,9 +35,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "url.com"); | |||
| Assert.AreEqual(r.title, "my title"); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "url.com"); | |||
| Assert.AreEqual(r.Title, "my title"); | |||
| } | |||
| [Test] | |||
| @@ -47,9 +47,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "url.com"); | |||
| Assert.AreEqual(r.title, "my title"); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "url.com"); | |||
| Assert.AreEqual(r.Title, "my title"); | |||
| } | |||
| [Test] | |||
| @@ -59,9 +59,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "url.com"); | |||
| Assert.AreEqual(r.title, "my title"); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "url.com"); | |||
| Assert.AreEqual(r.Title, "my title"); | |||
| } | |||
| [Test] | |||
| @@ -71,9 +71,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "url.com"); | |||
| Assert.AreEqual(r.title, "my title"); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "url.com"); | |||
| Assert.AreEqual(r.Title, "my title"); | |||
| } | |||
| [Test] | |||
| @@ -83,9 +83,9 @@ namespace MarkdownDeepTests | |||
| r = LinkDefinition.ParseLinkDefinition(str, false); | |||
| Assert.IsNotNull(r); | |||
| Assert.AreEqual(r.id, "id"); | |||
| Assert.AreEqual(r.url, "http://www.site.com"); | |||
| Assert.AreEqual(r.title, "my title"); | |||
| Assert.AreEqual(r.Id, "id"); | |||
| Assert.AreEqual(r.Url, "http://www.site.com"); | |||
| Assert.AreEqual(r.Title, "my title"); | |||
| } | |||
| [Test] | |||