Skip to content

Commit

Permalink
Added SummaryLength property
Browse files Browse the repository at this point in the history
  • Loading branch information
Brad Robinson committed Feb 3, 2011
1 parent 7895773 commit ff76243
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 74 deletions.
88 changes: 88 additions & 0 deletions MarkdownDeep/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ internal void RenderChildren(Markdown m, StringBuilder b)
}
}

internal void RenderChildrenPlain(Markdown m, StringBuilder b)
{
foreach (var block in children)
{
block.RenderPlain(m, b);
}
}

internal string ResolveHeaderID(Markdown m)
{
// Already resolved?
Expand Down Expand Up @@ -305,6 +313,86 @@ internal void Render(Markdown m, StringBuilder b)
}
}

internal void RenderPlain(Markdown m, StringBuilder b)
{
switch (blockType)
{
case BlockType.Blank:
return;

case BlockType.p:
case BlockType.span:
m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
b.Append(" ");
break;

case BlockType.h1:
case BlockType.h2:
case BlockType.h3:
case BlockType.h4:
case BlockType.h5:
case BlockType.h6:
m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
b.Append(" - ");
break;


case BlockType.ol_li:
case BlockType.ul_li:
b.Append("* ");
m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
b.Append(" ");
break;

case BlockType.dd:
if (children != null)
{
b.Append("\n");
RenderChildrenPlain(m, b);
}
else
m.SpanFormatter.FormatPlain(b, buf, contentStart, contentLen);
break;

case BlockType.dt:
{
if (children == null)
{
foreach (var l in Content.Split('\n'))
{
var str = l.Trim();
m.SpanFormatter.FormatPlain(b, str, 0, str.Length);
}
}
else
{
RenderChildrenPlain(m, b);
}
break;
}

case BlockType.dl:
RenderChildrenPlain(m, b);
return;

case BlockType.codeblock:
foreach (var line in children)
{
b.Append(line.buf, line.contentStart, line.contentLen);
b.Append(" ");
}
return;

case BlockType.quote:
case BlockType.li:
case BlockType.ol:
case BlockType.ul:
case BlockType.HtmlTag:
RenderChildrenPlain(m, b);
return;
}
}

public void RevertToPlain()
{
blockType = BlockType.p;
Expand Down
166 changes: 94 additions & 72 deletions MarkdownDeep/MardownDeep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public string Transform(string str, out Dictionary<string, LinkDefinition> defin
{
// Build blocks
var blocks = ProcessBlocks(str);

// Sort abbreviations by length, longest to shortest
if (m_AbbreviationMap!=null)
if (m_AbbreviationMap != null)
{
m_AbbreviationList = new List<Abbreviation>();
m_AbbreviationList.AddRange(m_AbbreviationMap.Values);
Expand All @@ -72,101 +72,117 @@ public string Transform(string str, out Dictionary<string, LinkDefinition> defin
);
}

// Render
// Setup string builder
StringBuilder sb = m_StringBuilderFinal;
sb.Length = 0;

int iSection = -1;

// Leading section (ie: plain text before first heading)
if (blocks.Count>0 && !IsSectionHeader(blocks[0]))
if (SummaryLength != 0)
{
iSection = 0;
OnSectionHeader(sb, 0);
OnSectionHeadingSuffix(sb, 0);
}
// Render all blocks
for (int i = 0; i < blocks.Count; i++)
{
var b = blocks[i];
b.RenderPlain(this, sb);

// Render all blocks
for (int i = 0; i < blocks.Count; i++)
if (SummaryLength>0 && sb.Length > SummaryLength)
break;
}

}
else
{
var b=blocks[i];
int iSection = -1;

// Leading section (ie: plain text before first heading)
if (blocks.Count > 0 && !IsSectionHeader(blocks[0]))
{
iSection = 0;
OnSectionHeader(sb, 0);
OnSectionHeadingSuffix(sb, 0);
}

// New section?
if (IsSectionHeader(b))
// Render all blocks
for (int i = 0; i < blocks.Count; i++)
{
// Finish the previous section
if (iSection >= 0)
var b = blocks[i];

// New section?
if (IsSectionHeader(b))
{
OnSectionFooter(sb, iSection);
}
// Finish the previous section
if (iSection >= 0)
{
OnSectionFooter(sb, iSection);
}

// Work out next section index
iSection = iSection < 0 ? 1 : iSection+1;
// Work out next section index
iSection = iSection < 0 ? 1 : iSection + 1;

// Section header
OnSectionHeader(sb, iSection);
// Section header
OnSectionHeader(sb, iSection);

// Section Heading
b.Render(this, sb);
// Section Heading
b.Render(this, sb);

// Section Heading suffix
OnSectionHeadingSuffix(sb, iSection);
}
else
{
// Regular section
b.Render(this, sb);
// Section Heading suffix
OnSectionHeadingSuffix(sb, iSection);
}
else
{
// Regular section
b.Render(this, sb);
}
}
}

// Finish final section
if (blocks.Count>0)
OnSectionFooter(sb, iSection);
// Finish final section
if (blocks.Count > 0)
OnSectionFooter(sb, iSection);

// Render footnotes
if (m_UsedFootnotes.Count > 0)
{
sb.Append("\n<div class=\"");
sb.Append(HtmlClassFootnotes);
sb.Append("\">\n");
sb.Append("<hr />\n");
sb.Append("<ol>\n");
for (int i=0; i<m_UsedFootnotes.Count; i++)
// Render footnotes
if (m_UsedFootnotes.Count > 0)
{
var fn=m_UsedFootnotes[i];

sb.Append("<li id=\"#fn:");
sb.Append((string)fn.data); // footnote id
sb.Append("\n<div class=\"");
sb.Append(HtmlClassFootnotes);
sb.Append("\">\n");
sb.Append("<hr />\n");
sb.Append("<ol>\n");
for (int i = 0; i < m_UsedFootnotes.Count; i++)
{
var fn = m_UsedFootnotes[i];

sb.Append("<li id=\"#fn:");
sb.Append((string)fn.data); // footnote id
sb.Append("\">\n");

// We need to get the return link appended to the last paragraph
// in the footnote
string strReturnLink = string.Format("<a href=\"#fnref:{0}\" rev=\"footnote\">&#8617;</a>", (string)fn.data);

// Get the last child of the footnote
var child = fn.children[fn.children.Count - 1];
if (child.blockType == BlockType.p)
{
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);
}
// We need to get the return link appended to the last paragraph
// in the footnote
string strReturnLink = string.Format("<a href=\"#fnref:{0}\" rev=\"footnote\">&#8617;</a>", (string)fn.data);

// Get the last child of the footnote
var child = fn.children[fn.children.Count - 1];
if (child.blockType == BlockType.p)
{
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);
}


fn.Render(this, sb);
fn.Render(this, sb);

sb.Append("</li>\n");
sb.Append("</li>\n");
}
sb.Append("</ol\n");
sb.Append("</div>\n");
}
sb.Append("</ol\n");
sb.Append("</div>\n");
}

definitions = m_LinkDefinitions;
Expand All @@ -175,6 +191,12 @@ public string Transform(string str, out Dictionary<string, LinkDefinition> defin
return sb.ToString();
}

public int SummaryLength
{
get;
set;
}

// Set to true to only allow whitelisted safe html tags
public bool SafeMode
{
Expand Down
65 changes: 65 additions & 0 deletions MarkdownDeep/SpanFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ internal void Format(StringBuilder dest, string str, int start, int len)
Render(dest, str);
}

internal void FormatPlain(StringBuilder dest, string str, int start, int len)
{
// Parse the string into a list of tokens
Tokenize(str, start, len);

// Render all tokens
RenderPlain(dest, str);
}

// Format a string and return it as a new string
// (used in formatting the text of links)
internal string Format(string str)
Expand Down Expand Up @@ -254,6 +263,62 @@ private void Render(StringBuilder sb, string str)
}
}

// Render a list of tokens to a destinatino string builder.
private void RenderPlain(StringBuilder sb, string str)
{
foreach (Token t in m_Tokens)
{
switch (t.type)
{
case TokenType.Text:
sb.Append(str, t.startOffset, t.length);
break;

case TokenType.HtmlTag:
break;

case TokenType.Html:
case TokenType.opening_mark:
case TokenType.closing_mark:
case TokenType.internal_mark:
break;

case TokenType.br:
break;

case TokenType.open_em:
case TokenType.close_em:
case TokenType.open_strong:
case TokenType.close_strong:
break;

case TokenType.code_span:
sb.Append(str, t.startOffset, t.length);
break;

case TokenType.link:
{
LinkInfo li = (LinkInfo)t.data;
sb.Append(li.link_text);
break;
}

case TokenType.img:
{
LinkInfo li = (LinkInfo)t.data;
sb.Append(li.link_text);
break;
}

case TokenType.footnote:
case TokenType.abbreviation:
break;
}

FreeToken(t);
}
}

// Scan the input string, creating tokens for anything special
public void Tokenize(string str, int start, int len)
{
Expand Down
Loading

0 comments on commit ff76243

Please sign in to comment.