// Parse just the link target // For reference link definition, this is the bit after "[id]: thisbit" // For inline link, this is the bit in the parens: [link text](thisbit) internal static LinkDefinition ParseLinkTarget(StringScanner p, string id, bool ExtraMode) { // Skip whitespace p.SkipWhitespace(); // End of string? if (p.eol) return null; // Create the link definition var r = new LinkDefinition(id); // Is the url enclosed in angle brackets if (p.SkipChar('<')) { // Extract the url p.Mark(); // Find end of the url while (p.current != '>') { if (p.eof) return null; p.SkipEscapableChar(ExtraMode); } string url = p.Extract(); if (!p.SkipChar('>')) return null; // Unescape it r.url = Utils.UnescapeString(url.Trim(), ExtraMode); // Skip whitespace p.SkipWhitespace(); } else { // Find end of the url p.Mark(); int paren_depth = 1; while (!p.eol) { char ch=p.current; if (char.IsWhiteSpace(ch)) break; if (id == null) { if (ch == '(') paren_depth++; else if (ch == ')') { paren_depth--; if (paren_depth==0) break; } } p.SkipEscapableChar(ExtraMode); } r.url = Utils.UnescapeString(p.Extract().Trim(), ExtraMode); } p.SkipLinespace(); // End of inline target if (p.DoesMatch(')')) return r; bool bOnNewLine = p.eol; int posLineEnd = p.position; if (p.eol) { p.SkipEol(); p.SkipLinespace(); } // Work out what the title is delimited with char delim; switch (p.current) { case '\'': case '\"': delim = p.current; break; case '(': delim = ')'; break; default: if (bOnNewLine) { p.position = posLineEnd; return r; } else return null; } // Skip the opening title delimiter p.SkipForward(1); // Find the end of the title p.Mark(); while (true) { if (p.eol) return null; if (p.current == delim) { if (delim != ')') { int savepos = p.position; // Check for embedded quotes in title // Skip the quote and any trailing whitespace p.SkipForward(1); p.SkipLinespace(); // 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)) { continue; } p.position = savepos; } // End of title break; } p.SkipEscapableChar(ExtraMode); } // Store the title r.title = Utils.UnescapeString(p.Extract(), ExtraMode); // Skip closing quote p.SkipForward(1); // Done! return r; }
// Parse just the link target // For reference link definition, this is the bit after "[id]: thisbit" // For inline link, this is the bit in the parens: [link text](thisbit) internal static LinkDefinition ParseLinkTarget(StringScanner p, string id, bool ExtraMode) { // Skip whitespace p.SkipWhitespace(); // End of string? if (p.eol) { return(null); } // Create the link definition var r = new LinkDefinition(id); // Is the url enclosed in angle brackets if (p.SkipChar('<')) { // Extract the url p.Mark(); // Find end of the url while (p.current != '>') { if (p.eof) { return(null); } p.SkipEscapableChar(ExtraMode); } string url = p.Extract(); if (!p.SkipChar('>')) { return(null); } // Unescape it r.url = Utils.UnescapeString(url.Trim(), ExtraMode); // Skip whitespace p.SkipWhitespace(); } else { // Find end of the url p.Mark(); int paren_depth = 1; while (!p.eol) { char ch = p.current; if (char.IsWhiteSpace(ch)) { break; } if (id == null) { if (ch == '(') { paren_depth++; } else if (ch == ')') { paren_depth--; if (paren_depth == 0) { break; } } } p.SkipEscapableChar(ExtraMode); } r.url = Utils.UnescapeString(p.Extract().Trim(), ExtraMode); } p.SkipLinespace(); // End of inline target if (p.DoesMatch(')')) { return(r); } bool bOnNewLine = p.eol; int posLineEnd = p.position; if (p.eol) { p.SkipEol(); p.SkipLinespace(); } // Work out what the title is delimited with char delim; switch (p.current) { case '\'': case '\"': delim = p.current; break; case '(': delim = ')'; break; default: if (bOnNewLine) { p.position = posLineEnd; return(r); } else { return(null); } } // Skip the opening title delimiter p.SkipForward(1); // Find the end of the title p.Mark(); while (true) { if (p.eol) { return(null); } if (p.current == delim) { if (delim != ')') { int savepos = p.position; // Check for embedded quotes in title // Skip the quote and any trailing whitespace p.SkipForward(1); p.SkipLinespace(); // 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)) { continue; } p.position = savepos; } // End of title break; } p.SkipEscapableChar(ExtraMode); } // Store the title r.title = Utils.UnescapeString(p.Extract(), ExtraMode); // Skip closing quote p.SkipForward(1); // Done! return(r); }
public List <TableCellDefinition> ParseRow(StringScanner p) { p.SkipLinespace(); if (p.eol) { return(null); // Blank line ends the table } bool bAnyBars = LeadingBar; if (LeadingBar && !p.SkipChar('|')) { return(null); } // Create the row List <TableCellDefinition> row = new List <TableCellDefinition>(); // Parse all columns except the last int totalColSpan = 0; while (!p.eol) { // Build new TableCellDefinition var cell = new TableCellDefinition(); bool bAlignLeft = false; bool bAlignRight = false; // Check custom cell alignment bAlignLeft = p.SkipChar(':'); // Check custom cell style if (p.SkipString("# ")) { cell.CellStyle = TableCellStyle.TH; } // Find the next vertical bar p.Mark(); while (!p.eol && p.current != '|') { p.SkipForward(1); } // Check custom cell alignment bAlignRight = p.DoesMatch(-2, " :"); // Get cell content cell.Content = p.Extract(0, (bAlignRight ? -2 : 0)).Trim(); // Get colspan bAnyBars |= p.SkipChar('|'); int colSpan = 1; while (p.SkipChar('|')) { colSpan++; } cell.ColSpan = colSpan; totalColSpan += colSpan; // Set cell alignment if (bAlignLeft && bAlignRight) { cell.Alignment = TableCellAlignment.Center; } else if (bAlignLeft) { cell.Alignment = TableCellAlignment.Left; } else if (bAlignRight) { cell.Alignment = TableCellAlignment.Right; } // Add cell to row row.Add(cell); } // Require at least one bar to continue the table if (!bAnyBars) { return(null); } // Add missing columns in Columns while (Columns.Count < totalColSpan) { Columns.Add(TableCellAlignment.NA); } p.SkipEol(); return(row); }
public List<TableCellDefinition> ParseRow(StringScanner p) { p.SkipLinespace(); if (p.eol) return null; // Blank line ends the table bool bAnyBars = LeadingBar; if (LeadingBar && !p.SkipChar('|')) { return null; } // Create the row List<TableCellDefinition> row = new List<TableCellDefinition>(); // Parse all columns except the last int totalColSpan = 0; while (!p.eol) { // Build new TableCellDefinition var cell = new TableCellDefinition(); bool bAlignLeft = false; bool bAlignRight = false; // Check custom cell alignment bAlignLeft = p.SkipChar(':'); // Check custom cell style if (p.SkipString("# ")) cell.CellStyle = TableCellStyle.TH; // Find the next vertical bar p.Mark(); while (!p.eol && p.current != '|') p.SkipForward(1); // Check custom cell alignment bAlignRight = p.DoesMatch(-2, " :"); // Get cell content cell.Content = p.Extract(0, (bAlignRight ? -2 : 0)).Trim(); // Get colspan bAnyBars |= p.SkipChar('|'); int colSpan = 1; while (p.SkipChar('|')) colSpan++; cell.ColSpan = colSpan; totalColSpan += colSpan; // Set cell alignment if (bAlignLeft && bAlignRight) cell.Alignment = TableCellAlignment.Center; else if (bAlignLeft) cell.Alignment = TableCellAlignment.Left; else if (bAlignRight) cell.Alignment = TableCellAlignment.Right; // Add cell to row row.Add(cell); } // Require at least one bar to continue the table if (!bAnyBars) return null; // Add missing columns in Columns while (Columns.Count < totalColSpan) Columns.Add(TableCellAlignment.NA); p.SkipEol(); return row; }