internal void RenderLink(Markdown m, StringBuilder b, string link_text) { if (url.StartsWith("mailto:")) { b.Append("<a href=\""); Utils.HtmlRandomize(b, url); b.Append('\"'); //if (!String.IsNullOrEmpty(title)) if (null != title && title != System.String.Empty) { b.Append(" title=\""); Utils.SmartHtmlEncodeAmpsAndAngles(b, title); b.Append('\"'); } b.Append('>'); Utils.HtmlRandomize(b, link_text); b.Append("</a>"); } else { HtmlTag tag = new HtmlTag("a"); // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); tag.attributes["href"] = sb.ToString(); // encode title //if (!String.IsNullOrEmpty(title )) if (null != title && title != System.String.Empty) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); tag.attributes["title"] = sb.ToString(); } // Do user processing m.OnPrepareLink(tag); // Render the opening tag tag.RenderOpening(b); b.Append(link_text); // Link text already escaped by SpanFormatter b.Append("</a>"); } }
public bool IsTagReallySafe(HtmlTag tag) { switch (tag.name) { case "B": case "UL": case "LI": case "I": return tag.attributes.Count == 0; case "A": case "a": return tag.closing && tag.attributes.Count == 0; } return false; }
internal MarkdownInHtmlMode GetMarkdownMode(HtmlTag tag) { // Get the markdown attribute string strMarkdownMode; if (!m_markdown.ExtraMode || !tag.attributes.TryGetValue("markdown", out strMarkdownMode)) { if (m_bMarkdownInHtml) return MarkdownInHtmlMode.Deep; else return MarkdownInHtmlMode.NA; } // Remove it tag.attributes.Remove("markdown"); // Parse mode if (strMarkdownMode == "1") return (tag.Flags & HtmlTagFlags.ContentAsSpan)!=0 ? MarkdownInHtmlMode.Span : MarkdownInHtmlMode.Block; if (strMarkdownMode == "block") return MarkdownInHtmlMode.Block; if (strMarkdownMode == "deep") return MarkdownInHtmlMode.Deep; if (strMarkdownMode == "span") return MarkdownInHtmlMode.Span; return MarkdownInHtmlMode.Off; }
internal void RenderVideo(Markdown m, StringBuilder b, string alt_text) { HtmlTag tag = new HtmlTag("video"); tag.attributes ["controls"] = "controls"; // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); HtmlTag source = new HtmlTag("source"); source.attributes["src"] = sb.ToString(); m.OnPrepareVideoSource(source); // encode alt text if (!String.IsNullOrEmpty(alt_text)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, alt_text); tag.attributes["alt"] = sb.ToString(); } // encode title if (!String.IsNullOrEmpty(title)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); tag.attributes["title"] = sb.ToString(); } tag.closed = true; tag.RenderOpening(b); source.RenderOpening (b); tag.RenderClosing (b); }
internal void RenderLink(Markdown m, StringBuilder b, string link_text, List <string> specialAttributes) { if (this.Url.StartsWith("mailto:")) { b.Append("<a href=\""); Utils.HtmlRandomize(b, this.Url); b.Append('\"'); if (!String.IsNullOrEmpty(this.Title)) { b.Append(" title=\""); Utils.SmartHtmlEncodeAmpsAndAngles(b, this.Title); b.Append('\"'); } b.Append('>'); Utils.HtmlRandomize(b, link_text); b.Append("</a>"); } else { HtmlTag tag = new HtmlTag("a"); var url = this.Url; if (m.DocNetMode && m.ConvertLocalLinks) { // A few requirements before we can convert local links: // 1. Link contains .md // 2. Link is relative // 3. Link is included in the index var index = url.LastIndexOf(".md", StringComparison.OrdinalIgnoreCase); if (index >= 0) { var linkProcessor = m.LocalLinkProcessor; if (linkProcessor != null) { url = linkProcessor(url); } if (Uri.TryCreate(url, UriKind.Relative, out var uri)) { url = String.Concat(url.Substring(0, index), ".htm", url.Substring(index + ".md".Length)); } } } // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); tag.attributes["href"] = sb.ToString(); // encode title if (!String.IsNullOrEmpty(this.Title)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Title); tag.attributes["title"] = sb.ToString(); } if (specialAttributes.Any()) { LinkDefinition.HandleSpecialAttributes(specialAttributes, sb, tag); } // Do user processing m.OnPrepareLink(tag); // Render the opening tag tag.RenderOpening(b); b.Append(link_text); // Link text already escaped by SpanFormatter b.Append("</a>"); } }
private static HtmlTag ParseHelper(StringScanner p) { // Does it look like a tag? if (p.Current != '<') return null; // Skip '<' p.SkipForward(1); // Is it a comment? if (p.SkipString("!--")) { p.Mark(); if (p.Find("-->")) { var t = new HtmlTag("!"); t.m_attributes.Add("content", p.Extract()); t.m_closed = true; p.SkipForward(3); return t; } } // Is it a closing tag eg: </div> bool bClosing = p.SkipChar('/'); // Get the tag name string tagName=null; if (!p.SkipIdentifier(ref tagName)) return null; // Probably a tag, create the HtmlTag object now HtmlTag tag = new HtmlTag(tagName); tag.m_closing = bClosing; // If it's a closing tag, no attributes if (bClosing) { if (p.Current != '>') return null; p.SkipForward(1); return tag; } while (!p.Eof) { // Skip whitespace p.SkipWhitespace(); // Check for closed tag eg: <hr /> if (p.SkipString("/>")) { tag.m_closed=true; return tag; } // End of tag? if (p.SkipChar('>')) { return tag; } // attribute name string attributeName = null; if (!p.SkipIdentifier(ref attributeName)) return null; // Skip whitespace p.SkipWhitespace(); // Skip equal sign if (p.SkipChar('=')) { // Skip whitespace p.SkipWhitespace(); // Optional quotes if (p.SkipChar('\"')) { // Scan the value p.Mark(); if (!p.Find('\"')) return null; // Store the value tag.m_attributes.Add(attributeName, p.Extract()); // Skip closing quote p.SkipForward(1); } else { // Scan the value p.Mark(); while (!p.Eof && !char.IsWhiteSpace(p.Current) && p.Current != '>' && p.Current != '/') p.SkipForward(1); if (!p.Eof) { // Store the value tag.m_attributes.Add(attributeName, p.Extract()); } } } else { tag.m_attributes.Add(attributeName, ""); } } return null; }
// Override to modify the attributes of an image public virtual void OnPrepareImage(HtmlTag tag, bool TitledImage) { if (PrepareImage != null) { if (PrepareImage(tag, TitledImage)) return; } // Try to determine width and height int width, height; if (OnGetImageSize(tag.attributes["src"], TitledImage, out width, out height)) { tag.attributes["width"] = width.ToString(); tag.attributes["height"] = height.ToString(); } // Now qualify the url tag.attributes["src"] = OnQualifyUrl(tag.attributes["src"]); }
private static bool PrepareImage(string imagesPath, HtmlTag tag) { string src; if (tag.attributes.TryGetValue("src", out src)) { src = src.Replace('\\', '/'); if (src.StartsWith("images/", StringComparison.InvariantCultureIgnoreCase)) src = src.Substring(7); tag.attributes["src"] = imagesPath + src; } return true; }
// Scan the input string, creating tokens for anything special public void Tokenize(string str, int start, int len) { // Prepare base.Reset(str, start, len); m_Tokens.Clear(); List <Token> emphasis_marks = null; List <Abbreviation> Abbreviations = m_Markdown.GetAbbreviations(); bool ExtraMode = m_Markdown.ExtraMode; // Scan string int start_text_token = Position; while (!Eof) { int end_text_token = Position; // Work out token Token token = null; int positionSave = Position; switch (Current) { case '*': case '_': // Create emphasis mark token = CreateEmphasisMark(); if (token != null) { // Store marks in a separate list the we'll resolve later switch (token.type) { case TokenType.internal_mark: case TokenType.opening_mark: case TokenType.closing_mark: if (emphasis_marks == null) { emphasis_marks = new List <Token>(); } emphasis_marks.Add(token); break; } } break; case '~': if (m_Markdown.HnDMode) { // scan for ~~text~~. token = ProcessStrikeThrough(); } break; case '`': token = ProcessCodeSpan(); break; case '[': case '!': // Process link reference int linkpos = Position; token = ProcessLinkOrImageOrFootnote(); // Rewind if invalid syntax // (the '[' or '!' will be treated as a regular character and processed below) if (token == null) { Position = linkpos; } break; case '<': // Is it a valid html tag? HtmlTag tag = HtmlTag.Parse(this); if (tag != null) { if (!m_Markdown.SafeMode || tag.IsSafe()) { // Yes, create a token for it token = CreateToken(TokenType.HtmlTag, positionSave, Position - positionSave); } else { // No, rewrite and encode it Position = positionSave; } } else { // No, rewind and check if it's a valid autolink eg: <google.com> Position = positionSave; token = ProcessAutoLink(); if (token == null) { Position = positionSave; } } break; case '&': // Is it a valid html entity string unused = null; if (SkipHtmlEntity(ref unused)) { // Yes, create a token for it token = CreateToken(TokenType.Html, positionSave, Position - positionSave); } break; case ' ': // Check for double space at end of a line if (CharAtOffset(1) == ' ' && IsLineEnd(CharAtOffset(2))) { // Yes, skip it SkipForward(2); // Don't put br's at the end of a paragraph if (!Eof) { SkipEol(); token = CreateToken(TokenType.br, end_text_token, 0); } } break; case '\\': // Special handling for escaping <autolinks> /* * if (CharAtOffset(1) == '<') * { * // Is it an autolink? * int savepos = position; * SkipForward(1); * bool AutoLink = ProcessAutoLink() != null; * position = savepos; * * if (AutoLink) * { * token = CreateToken(TokenType.Text, position + 1, 1); * SkipForward(2); * } * } * else */ { // Check followed by an escapable character if (Utils.IsEscapableChar(CharAtOffset(1), ExtraMode)) { token = CreateToken(TokenType.Text, Position + 1, 1); SkipForward(2); } } break; case '@': if (m_Markdown.DocNetMode || m_Markdown.HnDMode) { if (this.DoesMatch("@fa-")) { // expect FontAwesome. string iconName = string.Empty; int newPosition = 0; if (Utils.SkipFontAwesome(this.Input, this.Position, out newPosition, out iconName)) { // token should be just the iconname, so adjust position specification to that. token = CreateToken(TokenType.font_awesome, newPosition - iconName.Length, iconName.Length); this.Position = newPosition; } } } break; case ':': if (m_Markdown.HnDMode && m_Markdown.EmojiFilePerName != null) { // scan till next ':' and stop if EOL or whitespace is seen. string emojiName = string.Empty; int newPosition = 0; if (Utils.ParseEmoji(this.Input, this.Position, out newPosition, out emojiName)) { token = CreateToken(TokenType.emoji, emojiName); this.Position = newPosition; } else { // try smiley mapping token = ParseSmileyMapping(positionSave); } } break; default: token = ParseSmileyMapping(positionSave); break; } // Look for abbreviations. if (token == null && Abbreviations != null && !Char.IsLetterOrDigit(CharAtOffset(-1))) { var savepos = Position; foreach (var abbr in Abbreviations) { if (SkipString(abbr.Abbr) && !Char.IsLetterOrDigit(Current)) { token = CreateToken(TokenType.abbreviation, abbr); break; } Position = savepos; } } // If token found, append any preceeding text and the new token to the token list if (token != null) { // Create a token for everything up to the special character if (end_text_token > start_text_token) { m_Tokens.Add(CreateToken(TokenType.Text, start_text_token, end_text_token - start_text_token)); } // Add the new token m_Tokens.Add(token); // Remember where the next text token starts start_text_token = Position; } else { // Skip a single character and keep looking SkipForward(1); } } // Append a token for any trailing text after the last token. if (Position > start_text_token) { m_Tokens.Add(CreateToken(TokenType.Text, start_text_token, Position - start_text_token)); } // Do we need to resolve and emphasis marks? if (emphasis_marks != null) { ResolveEmphasisMarks(m_Tokens, emphasis_marks); } }
private static HtmlTag ParseHelper(StringScanner p) { // Does it look like a tag? if (p.current != '<') { return(null); } // Skip '<' p.SkipForward(1); // Is it a comment? if (p.SkipString("!--")) { p.Mark(); if (p.Find("-->")) { var t = new HtmlTag("!"); t.m_attributes.Add("content", p.Extract()); t.m_closed = true; p.SkipForward(3); return(t); } } // Is it a closing tag eg: </div> bool bClosing = p.SkipChar('/'); // Get the tag name string tagName = null; if (!p.SkipIdentifier(ref tagName)) { return(null); } // Probably a tag, create the HtmlTag object now HtmlTag tag = new HtmlTag(tagName); tag.m_closing = bClosing; // If it's a closing tag, no attributes if (bClosing) { if (p.current != '>') { return(null); } p.SkipForward(1); return(tag); } while (!p.eof) { // Skip whitespace p.SkipWhitespace(); // Check for closed tag eg: <hr /> if (p.SkipString("/>")) { tag.m_closed = true; return(tag); } // End of tag? if (p.SkipChar('>')) { return(tag); } // attribute name string attributeName = null; if (!p.SkipIdentifier(ref attributeName)) { return(null); } // Skip whitespace p.SkipWhitespace(); // <tag attr = "foo" /> // Skip equal sign if (p.SkipChar('=')) { // @kamranayub: Allow blank attributes per HTML spec // Skip whitespace p.SkipWhitespace(); // Optional quotes if (p.SkipChar('\"')) { // Scan the value p.Mark(); if (!p.Find('\"')) { return(null); } // Store the value tag.m_attributes.Add(attributeName, p.Extract()); // Skip closing quote p.SkipForward(1); } else { // Scan the value p.Mark(); while (!p.eof && !char.IsWhiteSpace(p.current) && p.current != '>' && p.current != '/') { p.SkipForward(1); } if (!p.eof) { // Store the value tag.m_attributes.Add(attributeName, p.Extract()); } } } else { tag.m_attributes.Add(attributeName, string.Empty); } } return(null); }
// Scan the input string, creating tokens for anything special public void Tokenize(string str, int start, int len) { // Prepare base.Reset(str, start, len); m_Tokens.Clear(); List<Token> emphasis_marks = null; List<Abbreviation> Abbreviations=m_Markdown.GetAbbreviations(); bool ExtraMode = m_Markdown.ExtraMode; // Scan string int start_text_token = position; while (!eof) { int end_text_token=position; // Work out token Token token = null; switch (current) { case '*': case '_': // Create emphasis mark token = CreateEmphasisMark(); if (token != null) { // Store marks in a separate list the we'll resolve later switch (token.type) { case TokenType.internal_mark: case TokenType.opening_mark: case TokenType.closing_mark: if (emphasis_marks == null) { emphasis_marks = new List<Token>(); } emphasis_marks.Add(token); break; } } break; case '`': token = ProcessCodeSpan(); break; case '[': case '!': { // Process link reference int linkpos = position; token = ProcessLinkOrImageOrFootnote(); // Rewind if invalid syntax // (the '[' or '!' will be treated as a regular character and processed below) if (token == null) position = linkpos; break; } case '<': { // Is it a valid html tag? int save = position; HtmlTag tag = HtmlTag.Parse(this); if (tag != null) { if (!m_Markdown.SafeMode || tag.IsSafe()) { // Yes, create a token for it token = CreateToken(TokenType.HtmlTag, save, position - save); } else { // No, rewrite and encode it position = save; } } else { // No, rewind and check if it's a valid autolink eg: <google.com> position = save; token = ProcessAutoLink(); if (token == null) position = save; } break; } case '&': { // Is it a valid html entity int save=position; string unused=null; if (SkipHtmlEntity(ref unused)) { // Yes, create a token for it token = CreateToken(TokenType.Html, save, position - save); } break; } case ' ': { // Check for double space at end of a line if (CharAtOffset(1)==' ' && IsLineEnd(CharAtOffset(2))) { // Yes, skip it SkipForward(2); // Don't put br's at the end of a paragraph if (!eof) { SkipEol(); token = CreateToken(TokenType.br, end_text_token, 0); } } break; } case '\\': { // Special handling for escaping <autolinks> /* if (CharAtOffset(1) == '<') { // Is it an autolink? int savepos = position; SkipForward(1); bool AutoLink = ProcessAutoLink() != null; position = savepos; if (AutoLink) { token = CreateToken(TokenType.Text, position + 1, 1); SkipForward(2); } } else */ { // Check followed by an escapable character if (Utils.IsEscapableChar(CharAtOffset(1), ExtraMode)) { token = CreateToken(TokenType.Text, position + 1, 1); SkipForward(2); } } break; } } // Look for abbreviations. if (token == null && Abbreviations!=null && !Char.IsLetterOrDigit(CharAtOffset(-1))) { var savepos = position; foreach (var abbr in Abbreviations) { if (SkipString(abbr.Abbr) && !Char.IsLetterOrDigit(current)) { token = CreateToken(TokenType.abbreviation, abbr); break; } position = savepos; } } // If token found, append any preceeding text and the new token to the token list if (token!=null) { // Create a token for everything up to the special character if (end_text_token > start_text_token) { m_Tokens.Add(CreateToken(TokenType.Text, start_text_token, end_text_token-start_text_token)); } // Add the new token m_Tokens.Add(token); // Remember where the next text token starts start_text_token=position; } else { // Skip a single character and keep looking SkipForward(1); } } // Append a token for any trailing text after the last token. if (position > start_text_token) { m_Tokens.Add(CreateToken(TokenType.Text, start_text_token, position-start_text_token)); } // Do we need to resolve and emphasis marks? if (emphasis_marks != null) { ResolveEmphasisMarks(m_Tokens, emphasis_marks); } // Done! return; }
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; } } }
internal void RenderLink(Markdown m, StringBuilder b, string link_text, List<string> specialAttributes) { if (this.Url.StartsWith("mailto:")) { b.Append("<a href=\""); Utils.HtmlRandomize(b, this.Url); b.Append('\"'); if (!String.IsNullOrEmpty(this.Title)) { b.Append(" title=\""); Utils.SmartHtmlEncodeAmpsAndAngles(b, this.Title); b.Append('\"'); } b.Append('>'); Utils.HtmlRandomize(b, link_text); b.Append("</a>"); } else { HtmlTag tag = new HtmlTag("a"); // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Url); tag.attributes["href"] = sb.ToString(); // encode title if (!String.IsNullOrEmpty(this.Title )) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Title); tag.attributes["title"] = sb.ToString(); } if(specialAttributes.Any()) { LinkDefinition.HandleSpecialAttributes(specialAttributes, sb, tag); } // Do user processing m.OnPrepareLink(tag); // Render the opening tag tag.RenderOpening(b); b.Append(link_text); // Link text already escaped by SpanFormatter b.Append("</a>"); } }
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); tag.attributes["src"] = sb.ToString(); // encode alt text if (!String.IsNullOrEmpty(alt_text)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, alt_text); tag.attributes["alt"] = sb.ToString(); } // encode title if (!String.IsNullOrEmpty(Title)) { sb.Length = 0; 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); tag.RenderOpening(b); }
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; } } }
internal bool ProcessMarkdownEnabledHtml(Block b, HtmlTag openingTag, MarkdownInHtmlMode mode) { // Current position is just after the opening tag // Scan until we find matching closing tag int inner_pos = position; int depth = 1; bool bHasUnsafeContent = false; while (!eof) { // Find next angle bracket if (!Find('<')) break; // Is it a html tag? int tagpos = position; HtmlTag tag = HtmlTag.Parse(this); if (tag == null) { // Nope, skip it SkipForward(1); continue; } // In markdown off mode, we need to check for unsafe tags if (m_markdown.SafeMode && mode == MarkdownInHtmlMode.Off && !bHasUnsafeContent) { if (!tag.IsSafe()) bHasUnsafeContent = true; } // Ignore self closing tags if (tag.closed) continue; // Same tag? if (tag.name == openingTag.name) { if (tag.closing) { depth--; if (depth == 0) { // End of tag? SkipLinespace(); SkipEol(); b.blockType = BlockType.HtmlTag; b.data = openingTag; b.contentEnd = position; switch (mode) { case MarkdownInHtmlMode.Span: { Block span = this.CreateBlock(); span.buf = input; span.blockType = BlockType.span; span.contentStart = inner_pos; span.contentLen = tagpos - inner_pos; b.children = new List<Block>(); b.children.Add(span); break; } case MarkdownInHtmlMode.Block: case MarkdownInHtmlMode.Deep: { // Scan the internal content var bp = new BlockProcessor(m_markdown, mode == MarkdownInHtmlMode.Deep); b.children = bp.ScanLines(input, inner_pos, tagpos - inner_pos); break; } case MarkdownInHtmlMode.Off: { if (bHasUnsafeContent) { b.blockType = BlockType.unsafe_html; b.contentEnd = position; } else { Block span = this.CreateBlock(); span.buf = input; span.blockType = BlockType.html; span.contentStart = inner_pos; span.contentLen = tagpos - inner_pos; b.children = new List<Block>(); b.children.Add(span); } break; } } return true; } } else { depth++; } } } // Missing closing tag(s). return false; }
private static bool PrepareLink(HtmlTag tag, string rootUrl, string trail, string versionUrl) { string href; if (!tag.attributes.TryGetValue("href", out href)) return true; if (Uri.IsWellFormedUriString(href, UriKind.Absolute)) return true; var hashIndex = href.IndexOf("#", StringComparison.InvariantCultureIgnoreCase); if (hashIndex != -1) href = href.Insert(hashIndex, "?version=" + versionUrl); else href += "?version=" + versionUrl; Uri uri; if (!string.IsNullOrWhiteSpace(trail)) trail += "/"; // make sure we don't lose the current slug if (!Uri.TryCreate(new Uri(rootUrl + trail, UriKind.Absolute), new Uri(href, UriKind.Relative), out uri)) { // TODO: Log error } tag.attributes["href"] = uri.AbsoluteUri; return true; }
private bool OnHtmlLink(HtmlTag arg) { var src = arg.attributes["href"]; if (src.StartsWith("http")) return false; if (src.StartsWith("~")) { src = VirtualPathHandler(src); arg.attributes["href"] = src; return true; } if (!src.StartsWith("/") && !src.StartsWith("#")) { src = _pageSource.GetAbsoluteUrl(_currentUrlPath, src); arg.attributes["href"] = VirtualPathHandler("~/" + _rootUri + "/" + src); } var exists = _pageSource.PageExists(src) || src.StartsWith("#"); if (!exists) arg.attributes["style"] = MissingLinkStyle; return true; }
private static bool PrepareLink(HtmlTag tag, string rootUrl, string trail, string versionUrl) { string href; if (!tag.attributes.TryGetValue("href", out href)) return true; if (Uri.IsWellFormedUriString(href, UriKind.Absolute)) return true; href += "?version=" + versionUrl; Uri uri; if (!string.IsNullOrWhiteSpace(trail)) trail += "/"; // make sure we don't lose the current slug if (!Uri.TryCreate(new Uri(rootUrl + trail, UriKind.Absolute), new Uri(href, UriKind.Relative), out uri)) { // TODO: Log error } tag.attributes["href"] = uri.AbsoluteUri; return true; }
private bool OnImageLink(HtmlTag arg1, bool arg2) { var src = arg1.attributes["src"]; if (src.StartsWith("http")) return false; if (src.StartsWith("~")) { //var url = string.Format(_rootUri + "?image={0}/{1}", _currentUrlPath, arg1.attributes["src"]); arg1.attributes["src"] = VirtualPathHandler(src); return true; } src = _pageSource.GetAbsoluteUrl(string.Empty, src); var formattedUrl = string.Format(VirtualPathHandler("~/" + _rootUri) + "?image={0}", src); arg1.attributes["src"] = formattedUrl; return true; }
// Override to modify the attributes of a link public virtual void OnPrepareLink(HtmlTag tag) { if (PrepareLink != null) { if (PrepareLink(tag)) return; } string url = tag.attributes["href"]; // No follow? if (NoFollowLinks) { tag.attributes["rel"] = "nofollow"; } // New window? if ( (NewWindowForExternalLinks && Utils.IsUrlFullyQualified(url)) || (NewWindowForLocalLinks && !Utils.IsUrlFullyQualified(url)) ) { tag.attributes["target"] = "_blank"; } // Qualify url tag.attributes["href"] = OnQualifyUrl(url); }
internal void RenderAudio(Markdown m, StringBuilder b, string alt_text) { HtmlTag tag = new HtmlTag("audio"); tag.attributes ["controls"] = "controls"; // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); tag.attributes["src"] = sb.ToString(); // encode alt text if (!String.IsNullOrEmpty(alt_text)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, alt_text); tag.attributes["alt"] = sb.ToString(); } // encode title if (!String.IsNullOrEmpty(title)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); tag.attributes["title"] = sb.ToString(); } tag.RenderOpening (b); tag.RenderClosing (b); }
internal void RenderImg(Markdown m, StringBuilder b, string alt_text) { HtmlTag tag = new HtmlTag("img"); // encode url StringBuilder sb = m.GetStringBuilder(); Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); tag.attributes["src"] = sb.ToString(); // encode alt text if (!String.IsNullOrEmpty(alt_text)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, alt_text); tag.attributes["alt"] = sb.ToString(); } // encode title if (!String.IsNullOrEmpty(title)) { sb.Length = 0; Utils.SmartHtmlEncodeAmpsAndAngles(sb, title); tag.attributes["title"] = sb.ToString(); } tag.closed = true; m.OnPrepareImage(tag, m.RenderingTitledImage); tag.RenderOpening(b); }
private static bool PrepareImage(ICollection<DocumentationImage> images, string directory, string imagesUrl, string documentationVersion, HtmlTag tag) { string src; if (tag.attributes.TryGetValue("src", out src)) { var imagePath = Path.Combine(directory, src); src = src.Replace('\\', '/'); if (src.StartsWith("images/", StringComparison.InvariantCultureIgnoreCase)) src = src.Substring(7); var newSrc = string.Format("{0}/{1}", documentationVersion, src); tag.attributes["src"] = imagesUrl + newSrc; images.Add(new DocumentationImage { ImagePath = imagePath, ImageKey = newSrc }); } tag.attributes["class"] = "img-responsive img-thumbnail"; return true; }