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; }
/// <summary> /// Handles the tab for tabs extension. This is a docnet extension and it handles: /// @tab tab head text /// tab content /// @end /// </summary> /// <param name="b">The current block.</param> /// <returns></returns> private bool HandleTabForTabsExtension(Block b) { // skip '@tab' if(!SkipString("@tab")) { return false; } SkipLinespace(); var tabHeaderTextStart = this.Position; // skip to eol, then grab the content between positions. SkipToEol(); var tabHeaderText = this.Input.Substring(tabHeaderTextStart, this.Position - tabHeaderTextStart); SkipToNextLine(); int startContent = this.Position; // find @end. if(!Find("@end")) { return false; } // Character before must be a eol char if(!IsLineEnd(CharAtOffset(-1))) { return false; } int endContent = Position; // skip @end SkipString("@end"); SkipLinespace(); if(!Eol) { return false; } // Remove the trailing line end endContent = UnskipCRLFBeforePos(endContent); b.BlockType = BlockType.tab; b.Data = tabHeaderText; // scan the content, as it can contain markdown statements. var contentProcessor = new BlockProcessor(m_markdown, m_markdown.MarkdownInHtml); b.Children = contentProcessor.ScanLines(Input, startContent, endContent - startContent); return true; }
private bool HandleTabsExtension(Block b) { // skip '@tabs' if(!SkipString("@tabs")) { return false; } // ignore what's specified behind @tabs SkipToNextLine(); int startContent = this.Position; // find @end. if(!Find("@endtabs")) { return false; } // Character before must be a eol char if(!IsLineEnd(CharAtOffset(-1))) { return false; } int endContent = Position; // skip @end SkipString("@endtabs"); SkipLinespace(); if(!Eol) { return false; } // Remove the trailing line end endContent = UnskipCRLFBeforePos(endContent); b.BlockType = BlockType.tabs; // scan the content, as it can contain markdown statements. var contentProcessor = new BlockProcessor(m_markdown, m_markdown.MarkdownInHtml); var scanLines = contentProcessor.ScanLines(this.Input, startContent, endContent - startContent); // check whether the content is solely tab blocks. If not, we ignore this tabs specification. if(scanLines.Any(x=>x.BlockType != BlockType.tab)) { return false; } b.Children = scanLines; return true; }
/// <summary> /// Handles the alert extension: /// @alert type /// text /// @end /// /// where text can be anything and has to be handled further. /// type is: danger, warning, info or neutral. /// </summary> /// <param name="b">The b.</param> /// <returns></returns> private bool HandleAlertExtension(Block b) { // skip '@alert' if(!SkipString("@alert")) { return false; } SkipLinespace(); var alertType = string.Empty; if(!SkipIdentifier(ref alertType)) { return false; } SkipToNextLine(); int startContent = this.Position; // find @end. if(!Find("@end")) { return false; } // Character before must be a eol char if(!IsLineEnd(CharAtOffset(-1))) { return false; } int endContent = Position; // skip @end SkipString("@end"); SkipLinespace(); if(!Eol) { return false; } // Remove the trailing line end endContent = UnskipCRLFBeforePos(endContent); b.BlockType = BlockType.alert; b.Data = alertType.ToLowerInvariant(); // scan the content, as it can contain markdown statements. var contentProcessor = new BlockProcessor(m_markdown, m_markdown.MarkdownInHtml); b.Children = contentProcessor.ScanLines(Input, startContent, endContent - startContent); return true; }