", dataArgument);
+ if(dataArgument == "nohighlight")
+ {
+ b.Append("");
+ tagSuffix = "
";
+ }
+ else
+ {
+ b.AppendFormat("", dataArgument);
+ }
}
else
{
b.Append("");
}
- foreach(var line in children)
+ foreach(var line in Children)
{
- m.HtmlEncodeAndConvertTabsToSpaces(b, line.buf, line.contentStart, line.contentLen);
+ m.HtmlEncodeAndConvertTabsToSpaces(b, line.Buf, line.ContentStart, line.ContentLen);
b.Append("\n");
}
- b.Append("
\n\n");
+ b.Append(tagSuffix);
}
else
{
var sb = new StringBuilder();
- foreach(var line in children)
+ foreach(var line in Children)
{
- m.HtmlEncodeAndConvertTabsToSpaces(sb, line.buf, line.contentStart, line.contentLen);
+ m.HtmlEncodeAndConvertTabsToSpaces(sb, line.Buf, line.ContentStart, line.ContentLen);
sb.Append("\n");
}
b.Append(m.FormatCodeBlockFunc(m, sb.ToString()));
@@ -315,7 +331,7 @@ namespace MarkdownDeep
return;
case BlockType.HtmlTag:
- var tag = (HtmlTag)data;
+ var tag = (HtmlTag)Data;
// Prepare special tags
var name=tag.name.ToLowerInvariant();
@@ -341,38 +357,55 @@ namespace MarkdownDeep
return;
case BlockType.table_spec:
- ((TableSpec)data).Render(m, b);
+ ((TableSpec)Data).Render(m, b);
break;
case BlockType.p_footnote:
b.Append("");
- if (contentLen > 0)
+ if (ContentLen > 0)
{
- m.SpanFormatter.Format(b, buf, contentStart, contentLen);
+ m.SpanFormatter.Format(b, Buf, ContentStart, ContentLen);
b.Append(" ");
}
- b.Append((string)data);
+ b.Append((string)Data);
b.Append("
\n");
break;
+// DocNet Extensions
+ case BlockType.font_awesome:
+ if(m.DocNetMode)
+ {
+ b.Append("");
+ }
+ break;
+ case BlockType.alert:
+ if(m.DocNetMode)
+ {
+ RenderAlert(m, b);
+ }
+ break;
+// End DocNet Extensions
default:
- b.Append("<" + blockType.ToString() + ">");
- m.SpanFormatter.Format(b, buf, contentStart, contentLen);
- b.Append("" + blockType.ToString() + ">\n");
+ b.Append("<" + BlockType.ToString() + ">");
+ m.SpanFormatter.Format(b, Buf, ContentStart, ContentLen);
+ b.Append("" + BlockType.ToString() + ">\n");
break;
}
}
+
internal void RenderPlain(Markdown m, StringBuilder b)
{
- switch (blockType)
+ switch (BlockType)
{
case BlockType.Blank:
return;
case BlockType.p:
case BlockType.span:
- m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
+ m.SpanFormatter.FormatPlain(b, Buf, ContentStart, ContentLen);
b.Append(" ");
break;
@@ -382,7 +415,7 @@ namespace MarkdownDeep
case BlockType.h4:
case BlockType.h5:
case BlockType.h6:
- m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
+ m.SpanFormatter.FormatPlain(b, Buf, ContentStart, ContentLen);
b.Append(" - ");
break;
@@ -390,23 +423,23 @@ namespace MarkdownDeep
case BlockType.ol_li:
case BlockType.ul_li:
b.Append("* ");
- m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
+ m.SpanFormatter.FormatPlain(b, Buf, ContentStart, ContentLen);
b.Append(" ");
break;
case BlockType.dd:
- if (children != null)
+ if (Children != null)
{
b.Append("\n");
RenderChildrenPlain(m, b);
}
else
- m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
+ m.SpanFormatter.FormatPlain(b, Buf, ContentStart, ContentLen);
break;
case BlockType.dt:
{
- if (children == null)
+ if (Children == null)
{
foreach (var l in Content.Split('\n'))
{
@@ -426,9 +459,9 @@ namespace MarkdownDeep
return;
case BlockType.codeblock:
- foreach (var line in children)
+ foreach (var line in Children)
{
- b.Append(line.buf, line.contentStart, line.contentLen);
+ b.Append(line.Buf, line.ContentStart, line.ContentLen);
b.Append(" ");
}
return;
@@ -445,34 +478,72 @@ namespace MarkdownDeep
public void RevertToPlain()
{
- blockType = BlockType.p;
- contentStart = lineStart;
- contentLen = lineLen;
+ BlockType = BlockType.p;
+ ContentStart = LineStart;
+ ContentLen = LineLen;
}
- public int contentEnd
+
+ private void RenderAlert(Markdown m, StringBuilder b)
+ {
+ var alertType = this.Data as string;
+ if(string.IsNullOrWhiteSpace(alertType))
+ {
+ alertType = "info";
+ }
+ string title = string.Empty;
+ string faIconName = string.Empty;
+ switch(alertType)
+ {
+ case "danger":
+ title = "Danger!";
+ faIconName = "times-circle";
+ break;
+ case "warning":
+ title = "Warning!";
+ faIconName = "warning";
+ break;
+ case "neutral":
+ case "info":
+ title = "Info";
+ faIconName = "info-circle";
+ break;
+ }
+ b.Append("");
+ b.Append(title);
+ b.Append("");
+ RenderChildren(m, b);
+ b.Append("");
+ }
+
+ #region Properties
+ public int ContentEnd
{
get
{
- return contentStart + contentLen;
+ return ContentStart + ContentLen;
}
set
{
- contentLen = value - contentStart;
+ ContentLen = value - ContentStart;
}
}
// Count the leading spaces on a block
// Used by list item evaluation to determine indent levels
// irrespective of indent line type.
- public int leadingSpaces
+ public int LeadingSpaces
{
get
{
int count = 0;
- for (int i = lineStart; i < lineStart + lineLen; i++)
+ for (int i = LineStart; i < LineStart + LineLen; i++)
{
- if (buf[i] == ' ')
+ if (Buf[i] == ' ')
{
count++;
}
@@ -488,27 +559,30 @@ namespace MarkdownDeep
public override string ToString()
{
string c = Content;
- return blockType.ToString() + " - " + (c==null ? "" : c);
+ return BlockType.ToString() + " - " + (c==null ? "" : c);
}
public Block CopyFrom(Block other)
{
- blockType = other.blockType;
- buf = other.buf;
- contentStart = other.contentStart;
- contentLen = other.contentLen;
- lineStart = other.lineStart;
- lineLen = other.lineLen;
+ BlockType = other.BlockType;
+ Buf = other.Buf;
+ ContentStart = other.ContentStart;
+ ContentLen = other.ContentLen;
+ LineStart = other.LineStart;
+ LineLen = other.LineLen;
return this;
}
- internal BlockType blockType;
- internal string buf;
- internal int contentStart;
- internal int contentLen;
- internal int lineStart;
- internal int lineLen;
- internal object data; // content depends on block type
- internal List children;
+
+ internal BlockType BlockType { get; set; }
+ internal string Buf { get; set; }
+ internal int ContentStart { get; set; }
+ internal int ContentLen { get; set; }
+ internal int LineStart { get; set; }
+ internal int LineLen { get; set; }
+ internal object Data { get; set; } // content depends on block type
+ internal List Children { get; set; }
+
+ #endregion
}
}
diff --git a/src/MarkdownDeep/BlockProcessor.cs b/src/MarkdownDeep/BlockProcessor.cs
index 0980d1b..2396382 100644
--- a/src/MarkdownDeep/BlockProcessor.cs
+++ b/src/MarkdownDeep/BlockProcessor.cs
@@ -21,6 +21,19 @@ namespace MarkdownDeep
{
public class BlockProcessor : StringScanner
{
+ #region Enums
+
+ internal enum MarkdownInHtmlMode
+ {
+ NA, // No markdown attribute on the tag
+ Block, // markdown=1 or markdown=block
+ Span, // markdown=1 or markdown=span
+ Deep, // markdown=deep - recursive block mode
+ Off, // Markdown="something else"
+ }
+
+ #endregion
+
public BlockProcessor(Markdown m, bool MarkdownInHtml)
{
m_markdown = m;
@@ -62,19 +75,19 @@ namespace MarkdownDeep
// Rewind, parse the header row then fast forward back to current pos
if (lines.Count == 1)
{
- int savepos = position;
- position = lines[0].lineStart;
+ int savepos = Position;
+ Position = lines[0].LineStart;
spec.Headers = spec.ParseRow(this);
if (spec.Headers == null)
return false;
- position = savepos;
+ Position = savepos;
lines.Clear();
}
// Parse all rows
while (true)
{
- int savepos = position;
+ int savepos = Position;
var row=spec.ParseRow(this);
if (row!=null)
@@ -83,7 +96,7 @@ namespace MarkdownDeep
continue;
}
- position = savepos;
+ Position = savepos;
break;
}
@@ -101,25 +114,25 @@ namespace MarkdownDeep
// Add all blocks
BlockType PrevBlockType = BlockType.unsafe_html;
- while (!eof)
+ while (!Eof)
{
// Remember if the previous line was blank
bool bPreviousBlank = PrevBlockType == BlockType.Blank;
// Get the next block
var b = EvaluateLine();
- PrevBlockType = b.blockType;
+ PrevBlockType = b.BlockType;
// For dd blocks, we need to know if it was preceeded by a blank line
// so store that fact as the block's data.
- if (b.blockType == BlockType.dd)
+ if (b.BlockType == BlockType.dd)
{
- b.data = bPreviousBlank;
+ b.Data = bPreviousBlank;
}
// SetExt header?
- if (b.blockType == BlockType.post_h1 || b.blockType == BlockType.post_h2)
+ if (b.BlockType == BlockType.post_h1 || b.BlockType == BlockType.post_h2)
{
if (lines.Count > 0)
{
@@ -128,11 +141,11 @@ namespace MarkdownDeep
CollapseLines(blocks, lines);
// If previous line was blank,
- if (prevline.blockType != BlockType.Blank)
+ if (prevline.BlockType != BlockType.Blank)
{
// Convert the previous line to a heading and add to block list
prevline.RevertToPlain();
- prevline.blockType = b.blockType == BlockType.post_h1 ? BlockType.h1 : BlockType.h2;
+ prevline.BlockType = b.BlockType == BlockType.post_h1 ? BlockType.h1 : BlockType.h2;
blocks.Add(prevline);
continue;
}
@@ -140,7 +153,7 @@ namespace MarkdownDeep
// Couldn't apply setext header to a previous line
- if (b.blockType == BlockType.post_h1)
+ if (b.BlockType == BlockType.post_h1)
{
// `===` gets converted to normal paragraph
b.RevertToPlain();
@@ -149,9 +162,9 @@ namespace MarkdownDeep
else
{
// `---` gets converted to hr
- if (b.contentLen >= 3)
+ if (b.ContentLen >= 3)
{
- b.blockType = BlockType.hr;
+ b.BlockType = BlockType.hr;
blocks.Add(b);
}
else
@@ -166,20 +179,20 @@ namespace MarkdownDeep
// Work out the current paragraph type
- BlockType currentBlockType = lines.Count > 0 ? lines[0].blockType : BlockType.Blank;
+ BlockType currentBlockType = lines.Count > 0 ? lines[0].BlockType : BlockType.Blank;
// Starting a table?
- if (b.blockType == BlockType.table_spec)
+ if (b.BlockType == BlockType.table_spec)
{
// Get the table spec, save position
- TableSpec spec = (TableSpec)b.data;
- int savepos = position;
+ TableSpec spec = (TableSpec)b.Data;
+ int savepos = Position;
if (!StartTable(spec, lines))
{
// Not a table, revert the tablespec row to plain,
// fast forward back to where we were up to and continue
// on as if nothing happened
- position = savepos;
+ Position = savepos;
b.RevertToPlain();
}
else
@@ -190,7 +203,7 @@ namespace MarkdownDeep
}
// Process this line
- switch (b.blockType)
+ switch (b.BlockType)
{
case BlockType.Blank:
switch (currentBlockType)
@@ -233,7 +246,7 @@ namespace MarkdownDeep
case BlockType.dd:
case BlockType.footnote:
var prevline = lines.Last();
- if (prevline.blockType == BlockType.Blank)
+ if (prevline.BlockType == BlockType.Blank)
{
CollapseLines(blocks, lines);
lines.Add(b);
@@ -266,7 +279,7 @@ namespace MarkdownDeep
case BlockType.p:
case BlockType.quote:
var prevline = lines.Last();
- if (prevline.blockType == BlockType.Blank)
+ if (prevline.BlockType == BlockType.Blank)
{
// Start a code block after a paragraph
CollapseLines(blocks, lines);
@@ -314,7 +327,7 @@ namespace MarkdownDeep
case BlockType.p:
case BlockType.quote:
var prevline = lines.Last();
- if (prevline.blockType == BlockType.Blank || m_parentType==BlockType.ol_li || m_parentType==BlockType.ul_li || m_parentType==BlockType.dd)
+ if (prevline.BlockType == BlockType.Blank || m_parentType==BlockType.ol_li || m_parentType==BlockType.ul_li || m_parentType==BlockType.dd)
{
// List starting after blank line after paragraph or quote
CollapseLines(blocks, lines);
@@ -330,7 +343,7 @@ namespace MarkdownDeep
case BlockType.ol_li:
case BlockType.ul_li:
- if (b.blockType!=BlockType.ol_li && b.blockType!=BlockType.ul_li)
+ if (b.BlockType!=BlockType.ol_li && b.BlockType!=BlockType.ul_li)
{
CollapseLines(blocks, lines);
}
@@ -339,7 +352,7 @@ namespace MarkdownDeep
case BlockType.dd:
case BlockType.footnote:
- if (b.blockType != currentBlockType)
+ if (b.BlockType != currentBlockType)
{
CollapseLines(blocks, lines);
}
@@ -412,7 +425,7 @@ namespace MarkdownDeep
StringBuilder b = m_markdown.GetStringBuilder();
foreach (var l in lines)
{
- b.Append(l.buf, l.contentStart, l.contentLen);
+ b.Append(l.Buf, l.ContentStart, l.ContentLen);
b.Append('\n');
}
return b.ToString();
@@ -421,7 +434,7 @@ namespace MarkdownDeep
internal void CollapseLines(List blocks, List lines)
{
// Remove trailing blank lines
- while (lines.Count>0 && lines.Last().blockType == BlockType.Blank)
+ while (lines.Count>0 && lines.Last().BlockType == BlockType.Blank)
{
FreeBlock(lines.Pop());
}
@@ -434,16 +447,16 @@ namespace MarkdownDeep
// What sort of block?
- switch (lines[0].blockType)
+ switch (lines[0].BlockType)
{
case BlockType.p:
{
// Collapse all lines into a single paragraph
var para = CreateBlock();
- para.blockType = BlockType.p;
- para.buf = lines[0].buf;
- para.contentStart = lines[0].contentStart;
- para.contentEnd = lines.Last().contentEnd;
+ para.BlockType = BlockType.p;
+ para.Buf = lines[0].Buf;
+ para.ContentStart = lines[0].ContentStart;
+ para.ContentEnd = lines.Last().ContentEnd;
blocks.Add(para);
FreeBlocks(lines);
break;
@@ -453,7 +466,7 @@ namespace MarkdownDeep
{
// Create a new quote block
var quote = new Block(BlockType.quote);
- quote.children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.quote).Process(RenderLines(lines));
+ quote.Children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.quote).Process(RenderLines(lines));
FreeBlocks(lines);
blocks.Add(quote);
break;
@@ -468,10 +481,10 @@ namespace MarkdownDeep
if (blocks.Count > 0)
{
var prev=blocks[blocks.Count-1];
- switch (prev.blockType)
+ switch (prev.BlockType)
{
case BlockType.p:
- prev.blockType = BlockType.dt;
+ prev.BlockType = BlockType.dt;
break;
case BlockType.dd:
@@ -479,9 +492,9 @@ namespace MarkdownDeep
default:
var wrapper = CreateBlock();
- wrapper.blockType = BlockType.dt;
- wrapper.children = new List();
- wrapper.children.Add(prev);
+ wrapper.BlockType = BlockType.dt;
+ wrapper.Children = new List();
+ wrapper.Children.Add(prev);
blocks.Pop();
blocks.Add(wrapper);
break;
@@ -510,8 +523,8 @@ namespace MarkdownDeep
}
}
*/
- codeblock.children = new List();
- codeblock.children.AddRange(lines);
+ codeblock.Children = new List();
+ codeblock.Children.AddRange(lines);
blocks.Add(codeblock);
lines.Clear();
break;
@@ -526,24 +539,24 @@ namespace MarkdownDeep
Block b=CreateBlock();
// Store line start
- b.lineStart=position;
- b.buf=input;
+ b.LineStart=Position;
+ b.Buf=Input;
// Scan the line
- b.contentStart = position;
- b.contentLen = -1;
- b.blockType=EvaluateLine(b);
+ b.ContentStart = Position;
+ b.ContentLen = -1;
+ b.BlockType=EvaluateLine(b);
// If end of line not returned, do it automatically
- if (b.contentLen < 0)
+ if (b.ContentLen < 0)
{
// Move to end of line
SkipToEol();
- b.contentLen = position - b.contentStart;
+ b.ContentLen = Position - b.ContentStart;
}
// Setup line length
- b.lineLen=position-b.lineStart;
+ b.LineLen=Position-b.LineStart;
// Next line
SkipEol();
@@ -555,20 +568,20 @@ namespace MarkdownDeep
BlockType EvaluateLine(Block b)
{
// Empty line?
- if (eol)
+ if (Eol)
return BlockType.Blank;
// Save start of line position
- int line_start= position;
+ int line_start= Position;
// ## Heading ##
- char ch=current;
+ char ch=Current;
if (ch == '#')
{
// Work out heading level
int level = 1;
SkipForward(1);
- while (current == '#')
+ while (Current == '#')
{
level++;
SkipForward(1);
@@ -582,7 +595,7 @@ namespace MarkdownDeep
SkipLinespace();
// Save start position
- b.contentStart = position;
+ b.ContentStart = Position;
// Jump to end
SkipToEol();
@@ -590,29 +603,29 @@ namespace MarkdownDeep
// In extra mode, check for a trailing HTML ID
if (m_markdown.ExtraMode && !m_markdown.SafeMode)
{
- int end=position;
- string strID = Utils.StripHtmlID(input, b.contentStart, ref end);
+ int end=Position;
+ string strID = Utils.StripHtmlID(Input, b.ContentStart, ref end);
if (strID!=null)
{
- b.data = strID;
- position = end;
+ b.Data = strID;
+ Position = end;
}
}
// Rewind over trailing hashes
- while (position>b.contentStart && CharAtOffset(-1) == '#')
+ while (Position>b.ContentStart && CharAtOffset(-1) == '#')
{
SkipForward(-1);
}
// Rewind over trailing spaces
- while (position>b.contentStart && char.IsWhiteSpace(CharAtOffset(-1)))
+ while (Position>b.ContentStart && char.IsWhiteSpace(CharAtOffset(-1)))
{
SkipForward(-1);
}
// Create the heading block
- b.contentEnd = position;
+ b.ContentEnd = Position;
SkipToEol();
return BlockType.h1 + (level - 1);
@@ -623,7 +636,7 @@ namespace MarkdownDeep
{
// Skip all matching characters
char chType = ch;
- while (current==chType)
+ while (Current==chType)
{
SkipForward(1);
}
@@ -632,12 +645,12 @@ namespace MarkdownDeep
SkipLinespace();
// If not at eol, must have found something other than setext header
- if (eol)
+ if (Eol)
{
return chType == '=' ? BlockType.post_h1 : BlockType.post_h2;
}
- position = line_start;
+ Position = line_start;
}
// MarkdownExtra Table row indicator?
@@ -646,37 +659,37 @@ namespace MarkdownDeep
TableSpec spec = TableSpec.Parse(this);
if (spec!=null)
{
- b.data = spec;
+ b.Data = spec;
return BlockType.table_spec;
}
- position = line_start;
+ Position = line_start;
}
// Fenced code blocks?
if((m_markdown.ExtraMode && (ch == '~' || ch=='`')) || (m_markdown.GitHubCodeBlocks && (ch=='`')))
{
if (ProcessFencedCodeBlock(b))
- return b.blockType;
+ return b.BlockType;
// Rewind
- position = line_start;
+ Position = line_start;
}
// Scan the leading whitespace, remembering how many spaces and where the first tab is
int tabPos = -1;
int leadingSpaces = 0;
- while (!eol)
+ while (!Eol)
{
- if (current == ' ')
+ if (Current == ' ')
{
if (tabPos < 0)
leadingSpaces++;
}
- else if (current == '\t')
+ else if (Current == '\t')
{
if (tabPos < 0)
- tabPos = position;
+ tabPos = Position;
}
else
{
@@ -687,41 +700,41 @@ namespace MarkdownDeep
}
// Blank line?
- if (eol)
+ if (Eol)
{
- b.contentEnd = b.contentStart;
+ b.ContentEnd = b.ContentStart;
return BlockType.Blank;
}
// 4 leading spaces?
if (leadingSpaces >= 4)
{
- b.contentStart = line_start + 4;
+ b.ContentStart = line_start + 4;
return BlockType.indent;
}
// Tab in the first 4 characters?
if (tabPos >= 0 && tabPos - line_start<4)
{
- b.contentStart = tabPos + 1;
+ b.ContentStart = tabPos + 1;
return BlockType.indent;
}
// Treat start of line as after leading whitespace
- b.contentStart = position;
+ b.ContentStart = Position;
// Get the next character
- ch = current;
+ ch = Current;
// Html block?
if (ch == '<')
{
// Scan html block
if (ScanHtml(b))
- return b.blockType;
+ return b.BlockType;
// Rewind
- position = b.contentStart;
+ Position = b.ContentStart;
}
// Block quotes start with '>' and have one space or one tab following
@@ -732,12 +745,12 @@ namespace MarkdownDeep
{
// Skip it and create quote block
SkipForward(2);
- b.contentStart = position;
+ b.ContentStart = Position;
return BlockType.quote;
}
SkipForward(1);
- b.contentStart = position;
+ b.ContentStart = Position;
return BlockType.quote;
}
@@ -745,17 +758,17 @@ namespace MarkdownDeep
if (ch == '-' || ch == '_' || ch == '*')
{
int count = 0;
- while (!eol)
+ while (!Eol)
{
- char chType = current;
- if (current == ch)
+ char chType = Current;
+ if (Current == ch)
{
count++;
SkipForward(1);
continue;
}
- if (IsLineSpace(current))
+ if (IsLineSpace(Current))
{
SkipForward(1);
continue;
@@ -764,7 +777,7 @@ namespace MarkdownDeep
break;
}
- if (eol && count >= 3)
+ if (Eol && count >= 3)
{
if (m_markdown.UserBreaks)
return BlockType.user_break;
@@ -773,7 +786,7 @@ namespace MarkdownDeep
}
// Rewind
- position = b.contentStart;
+ Position = b.ContentStart;
}
// Abbreviation definition?
@@ -783,13 +796,13 @@ namespace MarkdownDeep
SkipLinespace();
Mark();
- while (!eol && current != ']')
+ while (!Eol && Current != ']')
{
SkipForward(1);
}
var abbr = Extract().Trim();
- if (current == ']' && CharAtOffset(1) == ':' && !string.IsNullOrEmpty(abbr))
+ if (Current == ']' && CharAtOffset(1) == ':' && !string.IsNullOrEmpty(abbr))
{
SkipForward(2);
SkipLinespace();
@@ -805,7 +818,7 @@ namespace MarkdownDeep
return BlockType.Blank;
}
- position = b.contentStart;
+ Position = b.ContentStart;
}
// Unordered list
@@ -814,7 +827,7 @@ namespace MarkdownDeep
// Skip it
SkipForward(1);
SkipLinespace();
- b.contentStart = position;
+ b.ContentStart = Position;
return BlockType.ul_li;
}
@@ -823,7 +836,7 @@ namespace MarkdownDeep
{
SkipForward(1);
SkipLinespace();
- b.contentStart = position;
+ b.ContentStart = Position;
return BlockType.dd;
}
@@ -834,16 +847,16 @@ namespace MarkdownDeep
// Skip all digits
SkipForward(1);
- while (char.IsDigit(current))
+ while (char.IsDigit(Current))
SkipForward(1);
if (SkipChar('.') && SkipLinespace())
{
- b.contentStart = position;
+ b.ContentStart = Position;
return BlockType.ol_li;
}
- position=b.contentStart;
+ Position=b.ContentStart;
}
// Reference link definition?
@@ -852,7 +865,7 @@ namespace MarkdownDeep
// Footnote definition?
if (m_markdown.ExtraMode && CharAtOffset(1) == '^')
{
- var savepos = position;
+ var savepos = Position;
SkipForward(2);
@@ -860,12 +873,12 @@ namespace MarkdownDeep
if (SkipFootnoteID(out id) && SkipChar(']') && SkipChar(':'))
{
SkipLinespace();
- b.contentStart = position;
- b.data = id;
+ b.ContentStart = Position;
+ b.Data = id;
return BlockType.footnote;
}
- position = savepos;
+ Position = savepos;
}
// Parse a link definition
@@ -877,19 +890,22 @@ namespace MarkdownDeep
}
}
+ // DocNet '@' extensions
+ if(ch == '@' && m_markdown.DocNetMode)
+ {
+ if(HandleDocNetExtension(b))
+ {
+ return b.BlockType;
+ }
+
+ // Not valid, Rewind
+ Position = b.ContentStart;
+ }
+
// Nothing special
return BlockType.p;
}
- internal enum MarkdownInHtmlMode
- {
- NA, // No markdown attribute on the tag
- Block, // markdown=1 or markdown=block
- Span, // markdown=1 or markdown=span
- Deep, // markdown=deep - recursive block mode
- Off, // Markdown="something else"
- }
-
internal MarkdownInHtmlMode GetMarkdownMode(HtmlTag tag)
{
// Get the markdown attribute
@@ -926,17 +942,17 @@ namespace MarkdownDeep
// Current position is just after the opening tag
// Scan until we find matching closing tag
- int inner_pos = position;
+ int inner_pos = Position;
int depth = 1;
bool bHasUnsafeContent = false;
- while (!eof)
+ while (!Eof)
{
// Find next angle bracket
if (!Find('<'))
break;
// Is it a html tag?
- int tagpos = position;
+ int tagpos = Position;
HtmlTag tag = HtmlTag.Parse(this);
if (tag == null)
{
@@ -968,22 +984,22 @@ namespace MarkdownDeep
SkipLinespace();
SkipEol();
- b.blockType = BlockType.HtmlTag;
- b.data = openingTag;
- b.contentEnd = position;
+ 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;
+ span.Buf = Input;
+ span.BlockType = BlockType.span;
+ span.ContentStart = inner_pos;
+ span.ContentLen = tagpos - inner_pos;
- b.children = new List();
- b.children.Add(span);
+ b.Children = new List();
+ b.Children.Add(span);
break;
}
@@ -992,7 +1008,7 @@ namespace MarkdownDeep
{
// Scan the internal content
var bp = new BlockProcessor(m_markdown, mode == MarkdownInHtmlMode.Deep);
- b.children = bp.ScanLines(input, inner_pos, tagpos - inner_pos);
+ b.Children = bp.ScanLines(Input, inner_pos, tagpos - inner_pos);
break;
}
@@ -1000,19 +1016,19 @@ namespace MarkdownDeep
{
if (bHasUnsafeContent)
{
- b.blockType = BlockType.unsafe_html;
- b.contentEnd = position;
+ 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;
+ span.Buf = Input;
+ span.BlockType = BlockType.html;
+ span.ContentStart = inner_pos;
+ span.ContentLen = tagpos - inner_pos;
- b.children = new List();
- b.children.Add(span);
+ b.Children = new List();
+ b.Children.Add(span);
}
break;
}
@@ -1037,7 +1053,7 @@ namespace MarkdownDeep
internal bool ScanHtml(Block b)
{
// Remember start of html
- int posStartPiece = this.position;
+ int posStartPiece = this.Position;
// Parse a HTML tag
HtmlTag openingTag = HtmlTag.Parse(this);
@@ -1049,9 +1065,7 @@ namespace MarkdownDeep
return false;
// Safe mode?
- bool bHasUnsafeContent = false;
- if (m_markdown.SafeMode && !openingTag.IsSafe())
- bHasUnsafeContent = true;
+ bool bHasUnsafeContent = m_markdown.SafeMode && !openingTag.IsSafe();
HtmlTagFlags flags = openingTag.Flags;
@@ -1065,8 +1079,8 @@ namespace MarkdownDeep
SkipLinespace();
SkipEol();
- b.contentEnd = position;
- b.blockType = bHasUnsafeContent ? BlockType.unsafe_html : BlockType.html;
+ b.ContentEnd = Position;
+ b.BlockType = bHasUnsafeContent ? BlockType.unsafe_html : BlockType.html;
return true;
}
@@ -1075,13 +1089,13 @@ namespace MarkdownDeep
{
// Yes, opening tag must be on a line by itself
SkipLinespace();
- if (!eol)
+ if (!Eol)
return false;
}
// Head block extraction?
bool bHeadBlock = m_markdown.ExtractHeadBlocks && string.Compare(openingTag.name, "head", true) == 0;
- int headStart = this.position;
+ int headStart = this.Position;
// Work out the markdown mode for this element
if (!bHeadBlock && m_markdown.ExtraMode)
@@ -1098,14 +1112,14 @@ namespace MarkdownDeep
// Now capture everything up to the closing tag and put it all in a single HTML block
int depth = 1;
- while (!eof)
+ while (!Eof)
{
// Find next angle bracket
if (!Find('<'))
break;
// Save position of current tag
- int posStartCurrentTag = position;
+ int posStartCurrentTag = Position;
// Is it a html tag?
HtmlTag tag = HtmlTag.Parse(this);
@@ -1142,10 +1156,10 @@ namespace MarkdownDeep
if (posStartCurrentTag > posStartPiece)
{
Block htmlBlock = this.CreateBlock();
- htmlBlock.buf = input;
- htmlBlock.blockType = BlockType.html;
- htmlBlock.contentStart = posStartPiece;
- htmlBlock.contentLen = posStartCurrentTag - posStartPiece;
+ htmlBlock.Buf = Input;
+ htmlBlock.BlockType = BlockType.html;
+ htmlBlock.ContentStart = posStartPiece;
+ htmlBlock.ContentLen = posStartCurrentTag - posStartPiece;
childBlocks.Add(htmlBlock);
}
@@ -1154,7 +1168,7 @@ namespace MarkdownDeep
childBlocks.Add(markdownBlock);
// Remember start of the next piece
- posStartPiece = position;
+ posStartPiece = Position;
continue;
}
@@ -1180,8 +1194,8 @@ namespace MarkdownDeep
// If anything unsafe detected, just encode the whole block
if (bHasUnsafeContent)
{
- b.blockType = BlockType.unsafe_html;
- b.contentEnd = position;
+ b.BlockType = BlockType.unsafe_html;
+ b.ContentEnd = Position;
return true;
}
@@ -1189,21 +1203,21 @@ namespace MarkdownDeep
if (childBlocks != null)
{
// Create a block for the remainder
- if (position > posStartPiece)
+ if (Position > posStartPiece)
{
Block htmlBlock = this.CreateBlock();
- htmlBlock.buf = input;
- htmlBlock.blockType = BlockType.html;
- htmlBlock.contentStart = posStartPiece;
- htmlBlock.contentLen = position - posStartPiece;
+ htmlBlock.Buf = Input;
+ htmlBlock.BlockType = BlockType.html;
+ htmlBlock.ContentStart = posStartPiece;
+ htmlBlock.ContentLen = Position - posStartPiece;
childBlocks.Add(htmlBlock);
}
// Return a composite block
- b.blockType = BlockType.Composite;
- b.contentEnd = position;
- b.children = childBlocks;
+ b.BlockType = BlockType.Composite;
+ b.ContentEnd = Position;
+ b.Children = childBlocks;
return true;
}
@@ -1212,16 +1226,16 @@ namespace MarkdownDeep
{
var content = this.Substring(headStart, posStartCurrentTag - headStart);
m_markdown.HeadBlockContent = (m_markdown.HeadBlockContent ?? "") + content.Trim() + "\n";
- b.blockType = BlockType.html;
- b.contentStart = position;
- b.contentEnd = position;
- b.lineStart = position;
+ b.BlockType = BlockType.html;
+ b.ContentStart = Position;
+ b.ContentEnd = Position;
+ b.LineStart = Position;
return true;
}
// Straight html block
- b.blockType = BlockType.html;
- b.contentEnd = position;
+ b.BlockType = BlockType.html;
+ b.ContentEnd = Position;
return true;
}
}
@@ -1236,6 +1250,134 @@ namespace MarkdownDeep
return false;
}
+
+ ///
+ /// Handles the docnet extension, starting with '@'. This can be:
+ /// * @fa-
+ /// * @alert
+ /// @end
+ /// * @tabs
+ /// @tabsend
+ ///
+ /// The b.
+ /// true if extension was correctly handled, false otherwise (error)
+ private bool HandleDocNetExtension(Block b)
+ {
+ var initialStart = this.Position;
+ if(DoesMatch("@fa-"))
+ {
+ return HandleFontAwesomeExtension(b);
+ }
+ if(DoesMatch("@tabs"))
+ {
+ return HandleTabsExtension(b);
+ }
+ if(DoesMatch("@alert"))
+ {
+ return HandleAlertExtension(b);
+ }
+ return false;
+ }
+
+
+ ///
+ /// 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.
+ ///
+ /// The b.
+ ///
+ 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
+ if(Input[endContent - 1] == '\r' && Input[endContent - 2] == '\n')
+ {
+ endContent -= 2;
+ }
+ else
+ {
+ if(Input[endContent - 1] == '\n' && Input[endContent - 2] == '\r')
+ {
+ endContent -= 2;
+ }
+ else
+ {
+ endContent--;
+ }
+ }
+ b.BlockType = BlockType.alert;
+ b.Data = alertType;
+ // 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)
+ {
+#warning IMPLEMENT
+ return false;
+ }
+
+
+ ///
+ /// Handles the font awesome extension, which is available in DocNet mode. FontAwesome extension uses @fa-iconname, where iconname is the name of the fontawesome icon.
+ /// Called when '@fa-' has been seen. Current position is on 'f' of 'fa-'.
+ ///
+ /// The b.
+ ///
+ private bool HandleFontAwesomeExtension(Block b)
+ {
+ string iconName = string.Empty;
+ int newPosition = this.Position;
+ if(!Utils.SkipFontAwesome(this.Input, this.Position, out newPosition, out iconName))
+ {
+ return false;
+ }
+ this.Position = newPosition;
+ b.BlockType = BlockType.font_awesome;
+ b.Data = iconName;
+ return true;
+ }
+
+
/*
* Spacing
*
@@ -1249,7 +1391,7 @@ namespace MarkdownDeep
private Block BuildList(List lines)
{
// What sort of list are we dealing with
- BlockType listType = lines[0].blockType;
+ BlockType listType = lines[0].BlockType;
System.Diagnostics.Debug.Assert(listType == BlockType.ul_li || listType == BlockType.ol_li);
// Preprocess
@@ -1257,31 +1399,31 @@ namespace MarkdownDeep
// 2. Promote any unindented lines that have more leading space
// than the original list item to indented, including leading
// special chars
- int leadingSpace = lines[0].leadingSpaces;
+ int leadingSpace = lines[0].LeadingSpaces;
for (int i = 1; i < lines.Count; i++)
{
// Join plain paragraphs
- if ((lines[i].blockType == BlockType.p) &&
- (lines[i - 1].blockType == BlockType.p || lines[i - 1].blockType == BlockType.ul_li || lines[i - 1].blockType==BlockType.ol_li))
+ if ((lines[i].BlockType == BlockType.p) &&
+ (lines[i - 1].BlockType == BlockType.p || lines[i - 1].BlockType == BlockType.ul_li || lines[i - 1].BlockType==BlockType.ol_li))
{
- lines[i - 1].contentEnd = lines[i].contentEnd;
+ lines[i - 1].ContentEnd = lines[i].ContentEnd;
FreeBlock(lines[i]);
lines.RemoveAt(i);
i--;
continue;
}
- if (lines[i].blockType != BlockType.indent && lines[i].blockType != BlockType.Blank)
+ if (lines[i].BlockType != BlockType.indent && lines[i].BlockType != BlockType.Blank)
{
- int thisLeadingSpace = lines[i].leadingSpaces;
+ int thisLeadingSpace = lines[i].LeadingSpaces;
if (thisLeadingSpace > leadingSpace)
{
// Change line to indented, including original leading chars
// (eg: '* ', '>', '1.' etc...)
- lines[i].blockType = BlockType.indent;
- int saveend = lines[i].contentEnd;
- lines[i].contentStart = lines[i].lineStart + thisLeadingSpace;
- lines[i].contentEnd = saveend;
+ lines[i].BlockType = BlockType.indent;
+ int saveend = lines[i].ContentEnd;
+ lines[i].ContentStart = lines[i].LineStart + thisLeadingSpace;
+ lines[i].ContentEnd = saveend;
}
}
}
@@ -1289,21 +1431,21 @@ namespace MarkdownDeep
// Create the wrapping list item
var List = new Block(listType == BlockType.ul_li ? BlockType.ul : BlockType.ol);
- List.children = new List();
+ List.Children = new List();
// Process all lines in the range
for (int i = 0; i < lines.Count; i++)
{
- System.Diagnostics.Debug.Assert(lines[i].blockType == BlockType.ul_li || lines[i].blockType==BlockType.ol_li);
+ System.Diagnostics.Debug.Assert(lines[i].BlockType == BlockType.ul_li || lines[i].BlockType==BlockType.ol_li);
// Find start of item, including leading blanks
int start_of_li = i;
- while (start_of_li > 0 && lines[start_of_li - 1].blockType == BlockType.Blank)
+ while (start_of_li > 0 && lines[start_of_li - 1].BlockType == BlockType.Blank)
start_of_li--;
// Find end of the item, including trailing blanks
int end_of_li = i;
- while (end_of_li < lines.Count - 1 && lines[end_of_li + 1].blockType != BlockType.ul_li && lines[end_of_li + 1].blockType != BlockType.ol_li)
+ while (end_of_li < lines.Count - 1 && lines[end_of_li + 1].BlockType != BlockType.ul_li && lines[end_of_li + 1].BlockType != BlockType.ol_li)
end_of_li++;
// Is this a simple or complex list item?
@@ -1311,7 +1453,7 @@ namespace MarkdownDeep
{
// It's a simple, single line item item
System.Diagnostics.Debug.Assert(start_of_li == i);
- List.children.Add(CreateBlock().CopyFrom(lines[i]));
+ List.Children.Add(CreateBlock().CopyFrom(lines[i]));
}
else
{
@@ -1321,10 +1463,10 @@ namespace MarkdownDeep
for (int j = start_of_li; j <= end_of_li; j++)
{
var l = lines[j];
- sb.Append(l.buf, l.contentStart, l.contentLen);
+ sb.Append(l.Buf, l.ContentStart, l.ContentLen);
sb.Append('\n');
- if (lines[j].blockType == BlockType.Blank)
+ if (lines[j].BlockType == BlockType.Blank)
{
bAnyBlanks = true;
}
@@ -1332,22 +1474,22 @@ namespace MarkdownDeep
// Create the item and process child blocks
var item = new Block(BlockType.li);
- item.children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, listType).Process(sb.ToString());
+ item.Children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, listType).Process(sb.ToString());
// If no blank lines, change all contained paragraphs to plain text
if (!bAnyBlanks)
{
- foreach (var child in item.children)
+ foreach (var child in item.Children)
{
- if (child.blockType == BlockType.p)
+ if (child.BlockType == BlockType.p)
{
- child.blockType = BlockType.span;
+ child.BlockType = BlockType.span;
}
}
}
// Add the complex item
- List.children.Add(item);
+ List.Children.Add(item);
}
// Continue processing from end of li
@@ -1370,10 +1512,10 @@ namespace MarkdownDeep
for (int i = 1; i < lines.Count; i++)
{
// Join plain paragraphs
- if ((lines[i].blockType == BlockType.p) &&
- (lines[i - 1].blockType == BlockType.p || lines[i - 1].blockType == BlockType.dd))
+ if ((lines[i].BlockType == BlockType.p) &&
+ (lines[i - 1].BlockType == BlockType.p || lines[i - 1].BlockType == BlockType.dd))
{
- lines[i - 1].contentEnd = lines[i].contentEnd;
+ lines[i - 1].ContentEnd = lines[i].ContentEnd;
FreeBlock(lines[i]);
lines.RemoveAt(i);
i--;
@@ -1382,7 +1524,7 @@ namespace MarkdownDeep
}
// Single line definition
- bool bPreceededByBlank=(bool)lines[0].data;
+ bool bPreceededByBlank=(bool)lines[0].Data;
if (lines.Count==1 && !bPreceededByBlank)
{
var ret=lines[0];
@@ -1395,14 +1537,14 @@ namespace MarkdownDeep
for (int i = 0; i < lines.Count; i++)
{
var l = lines[i];
- sb.Append(l.buf, l.contentStart, l.contentLen);
+ sb.Append(l.Buf, l.ContentStart, l.ContentLen);
sb.Append('\n');
}
// Create the item and process child blocks
var item = this.CreateBlock();
- item.blockType = BlockType.dd;
- item.children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.dd).Process(sb.ToString());
+ item.BlockType = BlockType.dd;
+ item.Children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.dd).Process(sb.ToString());
FreeBlocks(lines);
lines.Clear();
@@ -1416,20 +1558,20 @@ namespace MarkdownDeep
Block currentList = null;
for (int i = 0; i < blocks.Count; i++)
{
- switch (blocks[i].blockType)
+ switch (blocks[i].BlockType)
{
case BlockType.dt:
case BlockType.dd:
if (currentList==null)
{
currentList=CreateBlock();
- currentList.blockType=BlockType.dl;
- currentList.children=new List();
+ currentList.BlockType=BlockType.dl;
+ currentList.Children=new List();
blocks.Insert(i, currentList);
i++;
}
- currentList.children.Add(blocks[i]);
+ currentList.Children.Add(blocks[i]);
blocks.RemoveAt(i);
i--;
break;
@@ -1447,10 +1589,10 @@ namespace MarkdownDeep
for (int i = 1; i < lines.Count; i++)
{
// Join plain paragraphs
- if ((lines[i].blockType == BlockType.p) &&
- (lines[i - 1].blockType == BlockType.p || lines[i - 1].blockType == BlockType.footnote))
+ if ((lines[i].BlockType == BlockType.p) &&
+ (lines[i - 1].BlockType == BlockType.p || lines[i - 1].BlockType == BlockType.footnote))
{
- lines[i - 1].contentEnd = lines[i].contentEnd;
+ lines[i - 1].ContentEnd = lines[i].ContentEnd;
FreeBlock(lines[i]);
lines.RemoveAt(i);
i--;
@@ -1463,15 +1605,15 @@ namespace MarkdownDeep
for (int i = 0; i < lines.Count; i++)
{
var l = lines[i];
- sb.Append(l.buf, l.contentStart, l.contentLen);
+ sb.Append(l.Buf, l.ContentStart, l.ContentLen);
sb.Append('\n');
}
// Create the item and process child blocks
var item = this.CreateBlock();
- item.blockType = BlockType.footnote;
- item.data = lines[0].data;
- item.children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.footnote).Process(sb.ToString());
+ item.BlockType = BlockType.footnote;
+ item.Data = lines[0].Data;
+ item.Children = new BlockProcessor(m_markdown, m_bMarkdownInHtml, BlockType.footnote).Process(sb.ToString());
FreeBlocks(lines);
lines.Clear();
@@ -1482,11 +1624,11 @@ namespace MarkdownDeep
bool ProcessFencedCodeBlock(Block b)
{
- char delim = current;
+ char delim = Current;
// Extract the fence
Mark();
- while (current == delim)
+ while (Current == delim)
SkipForward(1);
string strFence = Extract();
@@ -1501,7 +1643,7 @@ namespace MarkdownDeep
// allow space between first fence and name
SkipLinespace();
SkipIdentifier(ref languageName);
- b.data = string.IsNullOrWhiteSpace(languageName) ? "nohighlight" : languageName;
+ b.Data = string.IsNullOrWhiteSpace(languageName) ? "nohighlight" : languageName;
// skip linespace to EOL
SkipLinespace();
}
@@ -1509,13 +1651,13 @@ namespace MarkdownDeep
{
// Rest of line must be blank
SkipLinespace();
- if(!eol)
+ if(!Eol)
return false;
}
// Skip the eol and remember start of code
SkipEol();
- int startCode = position;
+ int startCode = Position;
// Find the end fence
if (!Find(strFence))
@@ -1525,35 +1667,35 @@ namespace MarkdownDeep
if (!IsLineEnd(CharAtOffset(-1)))
return false;
- int endCode = position;
+ int endCode = Position;
// Skip the fence
SkipForward(strFence.Length);
// Whitespace allowed at end
SkipLinespace();
- if (!eol)
+ if (!Eol)
return false;
// Create the code block
- b.blockType = BlockType.codeblock;
- b.children = new List();
+ b.BlockType = BlockType.codeblock;
+ b.Children = new List();
// Remove the trailing line end
- if (input[endCode - 1] == '\r' && input[endCode - 2] == '\n')
+ if (Input[endCode - 1] == '\r' && Input[endCode - 2] == '\n')
endCode -= 2;
- else if (input[endCode - 1] == '\n' && input[endCode - 2] == '\r')
+ else if (Input[endCode - 1] == '\n' && Input[endCode - 2] == '\r')
endCode -= 2;
else
endCode--;
// Create the child block with the entire content
var child = CreateBlock();
- child.blockType = BlockType.indent;
- child.buf = input;
- child.contentStart = startCode;
- child.contentEnd = endCode;
- b.children.Add(child);
+ child.BlockType = BlockType.indent;
+ child.Buf = Input;
+ child.ContentStart = startCode;
+ child.ContentEnd = endCode;
+ b.Children.Add(child);
return true;
}
diff --git a/src/MarkdownDeep/HtmlTag.cs b/src/MarkdownDeep/HtmlTag.cs
index aae5db7..70b950b 100644
--- a/src/MarkdownDeep/HtmlTag.cs
+++ b/src/MarkdownDeep/HtmlTag.cs
@@ -208,7 +208,7 @@ namespace MarkdownDeep
if (ret!=null)
{
- pos = sp.position;
+ pos = sp.Position;
return ret;
}
@@ -218,7 +218,7 @@ namespace MarkdownDeep
public static HtmlTag Parse(StringScanner p)
{
// Save position
- int savepos = p.position;
+ int savepos = p.Position;
// Parse it
var ret = ParseHelper(p);
@@ -226,14 +226,14 @@ namespace MarkdownDeep
return ret;
// Rewind if failed
- p.position = savepos;
+ p.Position = savepos;
return null;
}
private static HtmlTag ParseHelper(StringScanner p)
{
// Does it look like a tag?
- if (p.current != '<')
+ if (p.Current != '<')
return null;
// Skip '<'
@@ -270,7 +270,7 @@ namespace MarkdownDeep
// If it's a closing tag, no attributes
if (bClosing)
{
- if (p.current != '>')
+ if (p.Current != '>')
return null;
p.SkipForward(1);
@@ -278,7 +278,7 @@ namespace MarkdownDeep
}
- while (!p.eof)
+ while (!p.Eof)
{
// Skip whitespace
p.SkipWhitespace();
@@ -328,10 +328,10 @@ namespace MarkdownDeep
{
// Scan the value
p.Mark();
- while (!p.eof && !char.IsWhiteSpace(p.current) && p.current != '>' && p.current != '/')
+ while (!p.Eof && !char.IsWhiteSpace(p.Current) && p.Current != '>' && p.Current != '/')
p.SkipForward(1);
- if (!p.eof)
+ if (!p.Eof)
{
// Store the value
tag.m_attributes.Add(attributeName, p.Extract());
diff --git a/src/MarkdownDeep/LinkDefinition.cs b/src/MarkdownDeep/LinkDefinition.cs
index b60d51e..9ac9db4 100644
--- a/src/MarkdownDeep/LinkDefinition.cs
+++ b/src/MarkdownDeep/LinkDefinition.cs
@@ -146,10 +146,10 @@ namespace MarkdownDeep
// Parse a link definition
internal static LinkDefinition ParseLinkDefinition(StringScanner p, bool ExtraMode)
{
- int savepos=p.position;
+ int savepos=p.Position;
var l = ParseLinkDefinitionInternal(p, ExtraMode);
if (l==null)
- p.position = savepos;
+ p.Position = savepos;
return l;
}
@@ -180,7 +180,7 @@ namespace MarkdownDeep
p.SkipLinespace();
// Trailing crap, not a valid link reference...
- if (!p.eol)
+ if (!p.Eol)
return null;
return link;
@@ -195,7 +195,7 @@ namespace MarkdownDeep
p.SkipWhitespace();
// End of string?
- if (p.eol)
+ if (p.Eol)
return null;
// Create the link definition
@@ -208,9 +208,9 @@ namespace MarkdownDeep
p.Mark();
// Find end of the url
- while (p.current != '>')
+ while (p.Current != '>')
{
- if (p.eof)
+ if (p.Eof)
return null;
p.SkipEscapableChar(ExtraMode);
}
@@ -230,9 +230,9 @@ namespace MarkdownDeep
// Find end of the url
p.Mark();
int paren_depth = 1;
- while (!p.eol)
+ while (!p.Eol)
{
- char ch=p.current;
+ char ch=p.Current;
if (char.IsWhiteSpace(ch))
break;
if (id == null)
@@ -259,9 +259,9 @@ namespace MarkdownDeep
if (p.DoesMatch(')'))
return r;
- bool bOnNewLine = p.eol;
- int posLineEnd = p.position;
- if (p.eol)
+ bool bOnNewLine = p.Eol;
+ int posLineEnd = p.Position;
+ if (p.Eol)
{
p.SkipEol();
p.SkipLinespace();
@@ -269,11 +269,11 @@ namespace MarkdownDeep
// Work out what the title is delimited with
char delim;
- switch (p.current)
+ switch (p.Current)
{
case '\'':
case '\"':
- delim = p.current;
+ delim = p.Current;
break;
case '(':
@@ -283,7 +283,7 @@ namespace MarkdownDeep
default:
if (bOnNewLine)
{
- p.position = posLineEnd;
+ p.Position = posLineEnd;
return r;
}
else
@@ -297,15 +297,15 @@ namespace MarkdownDeep
p.Mark();
while (true)
{
- if (p.eol)
+ if (p.Eol)
return null;
- if (p.current == delim)
+ if (p.Current == delim)
{
if (delim != ')')
{
- int savepos = p.position;
+ int savepos = p.Position;
// Check for embedded quotes in title
@@ -315,13 +315,13 @@ namespace MarkdownDeep
// Next we expect either the end of the line for a link definition
// or the close bracket for an inline link
- if ((id == null && p.current != ')') ||
- (id != null && !p.eol))
+ if ((id == null && p.Current != ')') ||
+ (id != null && !p.Eol))
{
continue;
}
- p.position = savepos;
+ p.Position = savepos;
}
// End of title
diff --git a/src/MarkdownDeep/MardownDeep.cs b/src/MarkdownDeep/MardownDeep.cs
index 2e31917..6b1c585 100644
--- a/src/MarkdownDeep/MardownDeep.cs
+++ b/src/MarkdownDeep/MardownDeep.cs
@@ -178,28 +178,28 @@ namespace MarkdownDeep
var fn = m_UsedFootnotes[i];
sb.Append("\n");
// We need to get the return link appended to the last paragraph
// in the footnote
- string strReturnLink = string.Format("↩", (string)fn.data);
+ string strReturnLink = string.Format("↩", (string)fn.Data);
// Get the last child of the footnote
- var child = fn.children[fn.children.Count - 1];
- if (child.blockType == BlockType.p)
+ var child = fn.Children[fn.Children.Count - 1];
+ if (child.BlockType == BlockType.p)
{
- child.blockType = BlockType.p_footnote;
- child.data = strReturnLink;
+ child.BlockType = BlockType.p_footnote;
+ child.Data = strReturnLink;
}
else
{
child = CreateBlock();
- child.contentLen = 0;
- child.blockType = BlockType.p_footnote;
- child.data = strReturnLink;
- fn.children.Add(child);
+ child.ContentLen = 0;
+ child.BlockType = BlockType.p_footnote;
+ child.Data = strReturnLink;
+ fn.Children.Add(child);
}
@@ -420,7 +420,7 @@ namespace MarkdownDeep
private bool IsSectionHeader(Block b)
{
- return b.blockType >= BlockType.h1 && b.blockType <= BlockType.h3;
+ return b.BlockType >= BlockType.h1 && b.BlockType <= BlockType.h3;
}
@@ -441,10 +441,10 @@ namespace MarkdownDeep
for (int i = 0; i < blocks.Count; i++)
{
var b = blocks[i];
- if (b.blockType==BlockType.user_break)
+ if (b.BlockType==BlockType.user_break)
{
// Get the offset of the section
- int iSectionOffset = b.lineStart;
+ int iSectionOffset = b.LineStart;
// Add section
Sections.Add(markdown.Substring(iPrevSectionOffset, iSectionOffset - iPrevSectionOffset).Trim());
@@ -452,9 +452,9 @@ namespace MarkdownDeep
// Next section starts on next line
if (i + 1 < blocks.Count)
{
- iPrevSectionOffset = blocks[i + 1].lineStart;
+ iPrevSectionOffset = blocks[i + 1].LineStart;
if (iPrevSectionOffset==0)
- iPrevSectionOffset = blocks[i + 1].contentStart;
+ iPrevSectionOffset = blocks[i + 1].ContentStart;
}
else
iPrevSectionOffset = markdown.Length;
@@ -512,7 +512,7 @@ namespace MarkdownDeep
if (md.IsSectionHeader(b))
{
// Get the offset of the section
- int iSectionOffset = b.lineStart;
+ int iSectionOffset = b.LineStart;
// Add section
Sections.Add(markdown.Substring(iPrevSectionOffset, iSectionOffset - iPrevSectionOffset));
@@ -560,7 +560,7 @@ namespace MarkdownDeep
internal void AddFootnote(Block footnote)
{
- m_Footnotes[(string)footnote.data] = footnote;
+ m_Footnotes[(string)footnote.Data] = footnote;
}
// Look up a footnote, claim it and return it's index (or -1 if not found)
@@ -618,9 +618,9 @@ namespace MarkdownDeep
{
m_StringScanner.Reset(str, start, len);
var p = m_StringScanner;
- while (!p.eof)
+ while (!p.Eof)
{
- char ch = p.current;
+ char ch = p.Current;
switch (ch)
{
case '&':
@@ -654,9 +654,9 @@ namespace MarkdownDeep
m_StringScanner.Reset(str, start, len);
var p = m_StringScanner;
int pos = 0;
- while (!p.eof)
+ while (!p.Eof)
{
- char ch = p.current;
+ char ch = p.Current;
switch (ch)
{
case '\t':
@@ -826,6 +826,13 @@ namespace MarkdownDeep
set;
}
+
+ ///
+ /// Gets or sets a value indicating whether the parser is in DocNet mode. If set to true, it will handle '@' extensions added for DocNet as well as
+ /// collect H2 id elements.
+ ///
+ public bool DocNetMode { get; set; }
+
// When set, all html block level elements automatically support
// markdown syntax within them.
// (Similar to Pandoc's handling of markdown in html)
@@ -924,7 +931,7 @@ namespace MarkdownDeep
///
/// Collector for the created id's for H2 headers. First element in Tuple is id name, second is name for ToC (the text for H2). Id's are generated
- /// by the parser and use pandoc algorithm, as AutoHeadingId's is switched on.
+ /// by the parser and use pandoc algorithm, as AutoHeadingId's is switched on. Only in use if DocNetMode is set to true
///
public List> CreatedH2IdCollector { get; private set; }
diff --git a/src/MarkdownDeep/SpanFormatter.cs b/src/MarkdownDeep/SpanFormatter.cs
index 292c7cb..db534e4 100644
--- a/src/MarkdownDeep/SpanFormatter.cs
+++ b/src/MarkdownDeep/SpanFormatter.cs
@@ -137,18 +137,18 @@ namespace MarkdownDeep
base.Reset(sb.ToString());
// Skip everything up to the first letter
- while (!eof)
+ while (!Eof)
{
- if (Char.IsLetter(current))
+ if (Char.IsLetter(Current))
break;
SkipForward(1);
}
// Process all characters
sb.Length = 0;
- while (!eof)
+ while (!Eof)
{
- char ch = current;
+ char ch = Current;
if (char.IsLetterOrDigit(ch) || ch=='_' || ch=='-' || ch=='.')
sb.Append(Char.ToLower(ch));
else if (ch == ' ')
@@ -262,6 +262,12 @@ namespace MarkdownDeep
sb.Append("");
break;
}
+
+ case TokenType.font_awesome:
+ sb.Append("");
+ break;
}
FreeToken(t);
@@ -337,18 +343,18 @@ namespace MarkdownDeep
bool ExtraMode = m_Markdown.ExtraMode;
// Scan string
- int start_text_token = position;
- while (!eof)
+ int start_text_token = Position;
+ while (!Eof)
{
- int end_text_token=position;
+ int end_text_token=Position;
// Work out token
Token token = null;
- switch (current)
+ int positionSave = Position;
+ switch (Current)
{
case '*':
case '_':
-
// Create emphasis mark
token = CreateEmphasisMark();
@@ -376,64 +382,55 @@ namespace MarkdownDeep
case '[':
case '!':
- {
// Process link reference
- int linkpos = position;
+ 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;
+ 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);
+ token = CreateToken(TokenType.HtmlTag, positionSave, Position - positionSave);
}
else
{
// No, rewrite and encode it
- position = save;
+ Position = positionSave;
}
}
else
{
// No, rewind and check if it's a valid autolink eg:
- position = save;
+ Position = positionSave;
token = ProcessAutoLink();
if (token == null)
- position = save;
+ Position = positionSave;
}
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);
+ token = CreateToken(TokenType.Html, positionSave, Position - positionSave);
}
break;
- }
case ' ':
- {
// Check for double space at end of a line
if (CharAtOffset(1)==' ' && IsLineEnd(CharAtOffset(2)))
{
@@ -441,17 +438,15 @@ namespace MarkdownDeep
SkipForward(2);
// Don't put br's at the end of a paragraph
- if (!eof)
+ if (!Eof)
{
SkipEol();
token = CreateToken(TokenType.br, end_text_token, 0);
}
}
break;
- }
case '\\':
- {
// Special handling for escaping
/*
if (CharAtOffset(1) == '<')
@@ -474,27 +469,44 @@ namespace MarkdownDeep
// Check followed by an escapable character
if (Utils.IsEscapableChar(CharAtOffset(1), ExtraMode))
{
- token = CreateToken(TokenType.Text, position + 1, 1);
+ token = CreateToken(TokenType.Text, Position + 1, 1);
SkipForward(2);
}
}
break;
- }
+
+ case '@':
+ if(m_Markdown.DocNetMode)
+ {
+ 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;
}
// Look for abbreviations.
if (token == null && Abbreviations!=null && !Char.IsLetterOrDigit(CharAtOffset(-1)))
{
- var savepos = position;
+ var savepos = Position;
foreach (var abbr in Abbreviations)
{
- if (SkipString(abbr.Abbr) && !Char.IsLetterOrDigit(current))
+ if (SkipString(abbr.Abbr) && !Char.IsLetterOrDigit(Current))
{
token = CreateToken(TokenType.abbreviation, abbr);
break;
}
- position = savepos;
+ Position = savepos;
}
}
@@ -512,7 +524,7 @@ namespace MarkdownDeep
m_Tokens.Add(token);
// Remember where the next text token starts
- start_text_token=position;
+ start_text_token=Position;
}
else
{
@@ -522,9 +534,9 @@ namespace MarkdownDeep
}
// Append a token for any trailing text after the last token.
- if (position > start_text_token)
+ if (Position > start_text_token)
{
- m_Tokens.Add(CreateToken(TokenType.Text, start_text_token, 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?
@@ -532,9 +544,6 @@ namespace MarkdownDeep
{
ResolveEmphasisMarks(m_Tokens, emphasis_marks);
}
-
- // Done!
- return;
}
static bool IsEmphasisChar(char ch)
@@ -559,61 +568,61 @@ namespace MarkdownDeep
public Token CreateEmphasisMark()
{
// Capture current state
- char ch = current;
+ char ch = Current;
char altch = ch == '*' ? '_' : '*';
- int savepos = position;
+ int savepos = Position;
// Check for a consecutive sequence of just '_' and '*'
- if (bof || char.IsWhiteSpace(CharAtOffset(-1)))
+ if (Bof || char.IsWhiteSpace(CharAtOffset(-1)))
{
- while (IsEmphasisChar(current))
+ while (IsEmphasisChar(Current))
SkipForward(1);
- if (eof || char.IsWhiteSpace(current))
+ if (Eof || char.IsWhiteSpace(Current))
{
- return new Token(TokenType.Html, savepos, position - savepos);
+ return new Token(TokenType.Html, savepos, Position - savepos);
}
// Rewind
- position = savepos;
+ Position = savepos;
}
// Scan backwards and see if we have space before
while (IsEmphasisChar(CharAtOffset(-1)))
SkipForward(-1);
- bool bSpaceBefore = bof || char.IsWhiteSpace(CharAtOffset(-1));
- position = savepos;
+ bool bSpaceBefore = Bof || char.IsWhiteSpace(CharAtOffset(-1));
+ Position = savepos;
// Count how many matching emphasis characters
- while (current == ch)
+ while (Current == ch)
{
SkipForward(1);
}
- int count=position-savepos;
+ int count=Position-savepos;
// Scan forwards and see if we have space after
while (IsEmphasisChar(CharAtOffset(1)))
SkipForward(1);
- bool bSpaceAfter = eof || char.IsWhiteSpace(current);
- position = savepos + count;
+ bool bSpaceAfter = Eof || char.IsWhiteSpace(Current);
+ Position = savepos + count;
// This should have been stopped by check above
System.Diagnostics.Debug.Assert(!bSpaceBefore || !bSpaceAfter);
if (bSpaceBefore)
{
- return CreateToken(TokenType.opening_mark, savepos, position - savepos);
+ return CreateToken(TokenType.opening_mark, savepos, Position - savepos);
}
if (bSpaceAfter)
{
- return CreateToken(TokenType.closing_mark, savepos, position - savepos);
+ return CreateToken(TokenType.closing_mark, savepos, Position - savepos);
}
- if (m_Markdown.ExtraMode && ch == '_' && (Char.IsLetterOrDigit(current)))
+ if (m_Markdown.ExtraMode && ch == '_' && (Char.IsLetterOrDigit(Current)))
return null;
- return CreateToken(TokenType.internal_mark, savepos, position - savepos);
+ return CreateToken(TokenType.internal_mark, savepos, Position - savepos);
}
// Split mark token
@@ -656,7 +665,7 @@ namespace MarkdownDeep
break;
// Ignore if different type (ie: `*` vs `_`)
- if (input[opening_mark.startOffset] != input[closing_mark.startOffset])
+ if (Input[opening_mark.startOffset] != Input[closing_mark.startOffset])
continue;
// strong or em?
@@ -718,7 +727,7 @@ namespace MarkdownDeep
continue;
// Ignore if different type (ie: `*` vs `_`)
- if (input[opening_mark.startOffset] != input[closing_mark.startOffset])
+ if (Input[opening_mark.startOffset] != Input[closing_mark.startOffset])
continue;
// Must be at least two
@@ -764,7 +773,7 @@ namespace MarkdownDeep
continue;
// Ignore if different type (ie: `*` vs `_`)
- if (input[opening_mark.startOffset] != input[closing_mark.startOffset])
+ if (Input[opening_mark.startOffset] != Input[closing_mark.startOffset])
continue;
// Split the opening mark, keeping the LHS
@@ -884,9 +893,9 @@ namespace MarkdownDeep
bool ExtraMode = m_Markdown.ExtraMode;
// Allow anything up to the closing angle, watch for escapable characters
- while (!eof)
+ while (!Eof)
{
- char ch = current;
+ char ch = Current;
// No whitespace allowed
if (char.IsWhiteSpace(ch))
@@ -945,7 +954,7 @@ namespace MarkdownDeep
return null;
// Is it a foonote?
- var savepos=position;
+ var savepos=Position;
if (m_Markdown.ExtraMode && token_type==TokenType.link && SkipChar('^'))
{
SkipLinespace();
@@ -964,7 +973,7 @@ namespace MarkdownDeep
}
// Rewind
- position = savepos;
+ Position = savepos;
}
if (DisableLinks && token_type==TokenType.link)
@@ -976,9 +985,9 @@ namespace MarkdownDeep
// escapable characters
Mark();
int depth = 1;
- while (!eof)
+ while (!Eof)
{
- char ch = current;
+ char ch = Current;
if (ch == '[')
{
depth++;
@@ -994,7 +1003,7 @@ namespace MarkdownDeep
}
// Quit if end
- if (eof)
+ if (Eof)
return null;
// Get the link text and unescape it
@@ -1004,7 +1013,7 @@ namespace MarkdownDeep
SkipForward(1);
// Save position in case we need to rewind
- savepos = position;
+ savepos = Position;
// Inline links must follow immediately
if (SkipChar('('))
@@ -1029,7 +1038,7 @@ namespace MarkdownDeep
// If there's line end, we're allow it and as must line space as we want
// before the link id.
- if (eol)
+ if (Eol)
{
SkipEol();
SkipLinespace();
@@ -1037,7 +1046,7 @@ namespace MarkdownDeep
// Reference link?
string link_id = null;
- if (current == '[')
+ if (Current == '[')
{
// Skip the opening '['
SkipForward(1);
@@ -1056,7 +1065,7 @@ namespace MarkdownDeep
else
{
// Rewind to just after the closing ']'
- position = savepos;
+ Position = savepos;
}
// Link id not specified?
@@ -1087,7 +1096,7 @@ namespace MarkdownDeep
// Process a ``` code span ```
Token ProcessCodeSpan()
{
- int start = position;
+ int start = Position;
// Count leading ticks
int tickcount = 0;
@@ -1100,23 +1109,23 @@ namespace MarkdownDeep
SkipWhitespace();
// End?
- if (eof)
- return CreateToken(TokenType.Text, start, position - start);
+ if (Eof)
+ return CreateToken(TokenType.Text, start, Position - start);
- int startofcode = position;
+ int startofcode = Position;
// Find closing ticks
if (!Find(Substring(start, tickcount)))
- return CreateToken(TokenType.Text, start, position - start);
+ return CreateToken(TokenType.Text, start, Position - start);
// Save end position before backing up over trailing whitespace
- int endpos = position + tickcount;
+ int endpos = Position + tickcount;
while (char.IsWhiteSpace(CharAtOffset(-1)))
SkipForward(-1);
// Create the token, move back to the end and we're done
- var ret = CreateToken(TokenType.code_span, startofcode, position - startofcode);
- position = endpos;
+ var ret = CreateToken(TokenType.code_span, startofcode, Position - startofcode);
+ Position = endpos;
return ret;
}
diff --git a/src/MarkdownDeep/StringScanner.cs b/src/MarkdownDeep/StringScanner.cs
index 7d3be3b..ceaebee 100644
--- a/src/MarkdownDeep/StringScanner.cs
+++ b/src/MarkdownDeep/StringScanner.cs
@@ -84,7 +84,7 @@ namespace MarkdownDeep
}
// Get the entire input string
- public string input
+ public string Input
{
get
{
@@ -93,7 +93,7 @@ namespace MarkdownDeep
}
// Get the character at the current position
- public char current
+ public char Current
{
get
{
@@ -105,7 +105,7 @@ namespace MarkdownDeep
}
// Get/set the current position
- public int position
+ public int Position
{
get
{
@@ -119,11 +119,11 @@ namespace MarkdownDeep
// Get the remainder of the input
// (use this in a watch window while debugging :)
- public string remainder
+ public string Remainder
{
get
{
- return Substring(position);
+ return Substring(Position);
}
}
@@ -201,7 +201,7 @@ namespace MarkdownDeep
// Skip a character if present
public bool SkipChar(char ch)
{
- if (current == ch)
+ if (Current == ch)
{
SkipForward(1);
return true;
@@ -237,11 +237,11 @@ namespace MarkdownDeep
// Skip any whitespace
public bool SkipWhitespace()
{
- if (!char.IsWhiteSpace(current))
+ if (!char.IsWhiteSpace(Current))
return false;
SkipForward(1);
- while (char.IsWhiteSpace(current))
+ while (char.IsWhiteSpace(Current))
SkipForward(1);
return true;
@@ -256,11 +256,11 @@ namespace MarkdownDeep
// Skip spaces and tabs
public bool SkipLinespace()
{
- if (!IsLineSpace(current))
+ if (!IsLineSpace(Current))
return false;
SkipForward(1);
- while (IsLineSpace(current))
+ while (IsLineSpace(Current))
SkipForward(1);
return true;
@@ -269,7 +269,7 @@ namespace MarkdownDeep
// Does current character match something
public bool DoesMatch(char ch)
{
- return current == ch;
+ return Current == ch;
}
// Does character at offset match a character
@@ -314,7 +314,7 @@ namespace MarkdownDeep
// Does current string position match a string
public bool DoesMatchI(string str)
{
- return string.Compare(str, Substring(position, str.Length), true) == 0;
+ return string.Compare(str, Substring(Position, str.Length), true) == 0;
}
// Extract a substring
@@ -393,7 +393,7 @@ namespace MarkdownDeep
}
// Are we at eof?
- public bool eof
+ public bool Eof
{
get
{
@@ -402,16 +402,16 @@ namespace MarkdownDeep
}
// Are we at eol?
- public bool eol
+ public bool Eol
{
get
{
- return IsLineEnd(current);
+ return IsLineEnd(Current);
}
}
// Are we at bof?
- public bool bof
+ public bool Bof
{
get
{
@@ -437,7 +437,7 @@ namespace MarkdownDeep
// Skip an identifier
public bool SkipIdentifier(ref string identifier)
{
- int savepos = position;
+ int savepos = Position;
if (!Utils.ParseIdentifier(this.str, ref pos, ref identifier))
return false;
if (pos >= end)
@@ -450,7 +450,7 @@ namespace MarkdownDeep
public bool SkipFootnoteID(out string id)
{
- int savepos = position;
+ int savepos = Position;
SkipLinespace();
@@ -458,14 +458,14 @@ namespace MarkdownDeep
while (true)
{
- char ch = current;
+ char ch = Current;
if (char.IsLetterOrDigit(ch) || ch == '-' || ch == '_' || ch == ':' || ch == '.' || ch == ' ')
SkipForward(1);
else
break;
}
- if (position > mark)
+ if (Position > mark)
{
id = Extract().Trim();
if (!String.IsNullOrEmpty(id))
@@ -475,7 +475,7 @@ namespace MarkdownDeep
}
}
- position = savepos;
+ Position = savepos;
id = null;
return false;
}
@@ -483,7 +483,7 @@ namespace MarkdownDeep
// Skip a Html entity (eg: &)
public bool SkipHtmlEntity(ref string entity)
{
- int savepos = position;
+ int savepos = Position;
if (!Utils.SkipHtmlEntity(this.str, ref pos, ref entity))
return false;
if (pos > end)
diff --git a/src/MarkdownDeep/TableSpec.cs b/src/MarkdownDeep/TableSpec.cs
index 774cea7..8fa2430 100644
--- a/src/MarkdownDeep/TableSpec.cs
+++ b/src/MarkdownDeep/TableSpec.cs
@@ -44,7 +44,7 @@ namespace MarkdownDeep
{
p.SkipLinespace();
- if (p.eol)
+ if (p.Eol)
return null; // Blank line ends the table
bool bAnyBars=LeadingBar;
@@ -58,11 +58,11 @@ namespace MarkdownDeep
// Parse all columns except the last
- while (!p.eol)
+ while (!p.Eol)
{
// Find the next vertical bar
p.Mark();
- while (!p.eol && p.current != '|')
+ while (!p.Eol && p.Current != '|')
p.SkipEscapableChar(true);
row.Add(p.Extract().Trim());
@@ -143,7 +143,7 @@ namespace MarkdownDeep
p.SkipLinespace();
// Quick check for typical case
- if (p.current != '|' && p.current != ':' && p.current != '-')
+ if (p.Current != '|' && p.Current != ':' && p.Current != '-')
return null;
// Don't create the spec until it at least looks like one
@@ -164,11 +164,11 @@ namespace MarkdownDeep
p.SkipLinespace();
// Must have something in the spec
- if (p.current == '|')
+ if (p.Current == '|')
return null;
bool AlignLeft = p.SkipChar(':');
- while (p.current == '-')
+ while (p.Current == '-')
p.SkipForward(1);
bool AlignRight = p.SkipChar(':');
p.SkipLinespace();
@@ -182,7 +182,7 @@ namespace MarkdownDeep
else if (AlignRight)
col = ColumnAlignment.Right;
- if (p.eol)
+ if (p.Eol)
{
// Not a spec?
if (spec == null)
@@ -206,7 +206,7 @@ namespace MarkdownDeep
// Check for trailing vertical bar
p.SkipLinespace();
- if (p.eol)
+ if (p.Eol)
{
spec.TrailingBar = true;
return spec;
diff --git a/src/MarkdownDeep/Token.cs b/src/MarkdownDeep/Token.cs
index afdf2be..8478d97 100644
--- a/src/MarkdownDeep/Token.cs
+++ b/src/MarkdownDeep/Token.cs
@@ -52,6 +52,9 @@ namespace MarkdownDeep
opening_mark, // opening '*' or '_'
closing_mark, // closing '*' or '_'
internal_mark, // internal '*' or '_'
+
+ // DocNet Extensions
+ font_awesome, //
}
// Token
diff --git a/src/MarkdownDeep/Utils.cs b/src/MarkdownDeep/Utils.cs
index 2e8b820..a485a85 100644
--- a/src/MarkdownDeep/Utils.cs
+++ b/src/MarkdownDeep/Utils.cs
@@ -87,7 +87,7 @@ namespace MarkdownDeep
identifer = str.Substring(startpos, pos - startpos);
return true;
}
-
+
// Skip over anything that looks like a valid html entity (eg: &, {, nnn) etc...
// Updates `pos` to character after the entity if matched
public static bool SkipHtmlEntity(string str, ref int pos, ref string entity)
@@ -322,7 +322,7 @@ namespace MarkdownDeep
// Extension method. Skip an escapable character, or one normal character
public static void SkipEscapableChar(this StringScanner p, bool ExtraMode)
{
- if (p.current == '\\' && IsEscapableChar(p.CharAtOffset(1), ExtraMode))
+ if (p.Current == '\\' && IsEscapableChar(p.CharAtOffset(1), ExtraMode))
{
p.SkipForward(2);
}
@@ -367,16 +367,16 @@ namespace MarkdownDeep
StringBuilder sb = new StringBuilder();
StringScanner sp = new StringScanner(str);
- while (!sp.eof)
+ while (!sp.Eof)
{
- if (sp.eol)
+ if (sp.Eol)
{
sb.Append('\n');
sp.SkipEol();
}
else
{
- sb.Append(sp.current);
+ sb.Append(sp.Current);
sp.SkipForward(1);
}
}
@@ -491,5 +491,49 @@ namespace MarkdownDeep
return url.Contains("://") || url.StartsWith("mailto:");
}
+
+ ///
+ /// Skips the font awesome specification at the current specified pos. Pos is inside str at the '@'. font awesome
+ /// directives are @fa-iconname. newPos is positioned to character after iconname if successful match. iconname scanned is specified in iconname.
+ ///
+ /// The string.
+ /// The current position.
+ /// The new position.
+ /// Name of the icon.
+ ///
+ /// bool if match was found and properly skipped, otherwise false.
+ ///
+ public static bool SkipFontAwesome(string str, int currentPos, out int newPos, out string iconName)
+ {
+ newPos = currentPos;
+ iconName = string.Empty;
+ if(str[currentPos] != '@')
+ {
+ return false;
+ }
+
+ var scanner = new StringScanner(str, currentPos);
+ // skip '@'
+ scanner.SkipForward(1);
+ if(!scanner.DoesMatch("fa-"))
+ {
+ // not a font awesome specification
+ return false;
+ }
+ scanner.SkipForward(3);
+ iconName = string.Empty;
+ if(!scanner.SkipIdentifier(ref iconName))
+ {
+ // no icon name specified
+ return false;
+ }
+ if(string.IsNullOrWhiteSpace(iconName))
+ {
+ return false;
+ }
+ // matched a fontawesome specification
+ newPos = scanner.Position;
+ return true;
+ }
}
}
diff --git a/src/MarkdownDeepTests/BlockProcessorTests.cs b/src/MarkdownDeepTests/BlockProcessorTests.cs
index 917733f..c8c1ac2 100644
--- a/src/MarkdownDeepTests/BlockProcessorTests.cs
+++ b/src/MarkdownDeepTests/BlockProcessorTests.cs
@@ -21,7 +21,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("paragraph");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.p, b[0].blockType);
+ Assert.AreEqual(BlockType.p, b[0].BlockType);
Assert.AreEqual("paragraph", b[0].Content);
}
@@ -30,7 +30,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("l1\nl2\n\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.p, b[0].blockType);
+ Assert.AreEqual(BlockType.p, b[0].BlockType);
Assert.AreEqual("l1\nl2", b[0].Content);
}
@@ -39,7 +39,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("heading\n===\n\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.h1, b[0].blockType);
+ Assert.AreEqual(BlockType.h1, b[0].BlockType);
Assert.AreEqual("heading", b[0].Content);
}
@@ -48,7 +48,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("heading\n---\n\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.h2, b[0].blockType);
+ Assert.AreEqual(BlockType.h2, b[0].BlockType);
Assert.AreEqual("heading", b[0].Content);
}
@@ -58,13 +58,13 @@ namespace MarkdownDeepTests
var b = p.Process("p1\nheading\n---\np2\n");
Assert.AreEqual(3, b.Count);
- Assert.AreEqual(BlockType.p, b[0].blockType);
+ Assert.AreEqual(BlockType.p, b[0].BlockType);
Assert.AreEqual("p1", b[0].Content);
- Assert.AreEqual(BlockType.h2, b[1].blockType);
+ Assert.AreEqual(BlockType.h2, b[1].BlockType);
Assert.AreEqual("heading", b[1].Content);
- Assert.AreEqual(BlockType.p, b[2].blockType);
+ Assert.AreEqual(BlockType.p, b[2].BlockType);
Assert.AreEqual("p2", b[2].Content);
}
@@ -74,10 +74,10 @@ namespace MarkdownDeepTests
var b = p.Process("#heading#\nparagraph\n");
Assert.AreEqual(2, b.Count);
- Assert.AreEqual(BlockType.h1, b[0].blockType);
+ Assert.AreEqual(BlockType.h1, b[0].BlockType);
Assert.AreEqual("heading", b[0].Content);
- Assert.AreEqual(BlockType.p, b[1].blockType);
+ Assert.AreEqual(BlockType.p, b[1].BlockType);
Assert.AreEqual("paragraph", b[1].Content);
}
@@ -88,13 +88,13 @@ namespace MarkdownDeepTests
Assert.AreEqual(3, b.Count);
- Assert.AreEqual(BlockType.p, b[0].blockType);
+ Assert.AreEqual(BlockType.p, b[0].BlockType);
Assert.AreEqual("p1", b[0].Content);
- Assert.AreEqual(BlockType.h2, b[1].blockType);
+ Assert.AreEqual(BlockType.h2, b[1].BlockType);
Assert.AreEqual("heading", b[1].Content);
- Assert.AreEqual(BlockType.p, b[2].blockType);
+ Assert.AreEqual(BlockType.p, b[2].BlockType);
Assert.AreEqual("p2", b[2].Content);
}
@@ -107,7 +107,7 @@ namespace MarkdownDeepTests
Block cb = b[0] as Block;
Assert.AreEqual("code1\n\tcode2\ncode3\n", cb.Content);
- Assert.AreEqual(BlockType.p, b[1].blockType);
+ Assert.AreEqual(BlockType.p, b[1].BlockType);
Assert.AreEqual("paragraph", b[1].Content);
}
@@ -116,7 +116,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("\n\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.html, b[0].blockType);
+ Assert.AreEqual(BlockType.html, b[0].BlockType);
Assert.AreEqual("\n\n", b[0].Content);
}
@@ -125,7 +125,7 @@ namespace MarkdownDeepTests
{
var b = p.Process("\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.html, b[0].blockType);
+ Assert.AreEqual(BlockType.html, b[0].BlockType);
Assert.AreEqual("\n", b[0].Content);
}
@@ -134,27 +134,27 @@ namespace MarkdownDeepTests
{
var b = p.Process("---\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
b = p.Process("___\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
b = p.Process("***\n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
b = p.Process(" - - - \n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
b = p.Process(" _ _ _ \n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
b = p.Process(" * * * \n");
Assert.AreEqual(1, b.Count);
- Assert.AreEqual(BlockType.hr, b[0].blockType);
+ Assert.AreEqual(BlockType.hr, b[0].BlockType);
}
diff --git a/src/MarkdownDeepTests/DocNetMode.cs b/src/MarkdownDeepTests/DocNetMode.cs
new file mode 100644
index 0000000..f6cdd3c
--- /dev/null
+++ b/src/MarkdownDeepTests/DocNetMode.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using MarkdownDeep;
+using System.Reflection;
+
+namespace MarkdownDeepTests
+{
+ [TestFixture]
+ class DocNetModeTests
+ {
+ public static IEnumerable GetTests()
+ {
+ return Utils.GetTests("docnetmode");
+ }
+
+
+ [Test, TestCaseSource("GetTests")]
+ public void Test(string resourceName)
+ {
+ Utils.RunResourceTest(resourceName);
+ }
+ }
+}
diff --git a/src/MarkdownDeepTests/MarkdownDeepTests.csproj b/src/MarkdownDeepTests/MarkdownDeepTests.csproj
index d1602cb..1babcd2 100644
--- a/src/MarkdownDeepTests/MarkdownDeepTests.csproj
+++ b/src/MarkdownDeepTests/MarkdownDeepTests.csproj
@@ -70,6 +70,7 @@
+
@@ -454,6 +455,18 @@
MarkdownDeep
+
+
+
+
+
+
+
+
+
+
+
+