public void Tests() { var p = new StringScanner(); p.Reset("This is a string with something [bracketed]"); Assert.IsTrue(p.Bof); Assert.IsFalse(p.Eof); Assert.IsTrue(p.SkipString("This")); Assert.IsFalse(p.Bof); Assert.IsFalse(p.Eof); Assert.IsFalse(p.SkipString("huh?")); Assert.IsTrue(p.SkipLinespace()); Assert.IsTrue(p.SkipChar('i')); Assert.IsTrue(p.SkipChar('s')); Assert.IsTrue(p.SkipWhitespace()); Assert.IsTrue(p.DoesMatchAny(new char[] { 'r', 'a', 't'} )); Assert.IsFalse(p.Find("Not here")); Assert.IsFalse(p.Find("WITH")); Assert.IsFalse(p.FindI("Not here")); Assert.IsTrue(p.FindI("WITH")); Assert.IsTrue(p.Find('[')); p.SkipForward(1); p.Mark(); Assert.IsTrue(p.Find(']')); Assert.AreEqual("bracketed", p.Extract()); Assert.IsTrue(p.SkipChar(']')); Assert.IsTrue(p.Eof); }
/// <summary> /// Strips the special attributes specified at the location of start. Special attributes are a php markdown extension /// and specified between {}. Attributes are separated with spaces. It recognizes the following attributes: /// id, which start with a '#'. Only the first one is used /// css classes, which start with a'.'. All specified are used /// name=value pairs, which will end up as attributes on the element. /// </summary> /// <param name="str">The string we're scanning.</param> /// <param name="start">The start (current) position.</param> /// <param name="end">The end position. Is only valid if returned list contains at least one value.</param> /// <returns>list of special attributes found, or null if none found or error in string format.</returns> public static List <string> StripSpecialAttributes(string str, int start, out int end) { end = start; var scanner = new StringScanner(str, start); if (!scanner.DoesMatch('{')) { // not a start of a special attribute block return(null); } // first find the end of the block, scanner.SkipForward(1); var startOfAttributes = scanner.Position; // first find the next EOL, as the closing } has to be on this line. scanner.SkipToEol(); var nextEolPos = scanner.Position; scanner.Position = startOfAttributes; scanner.Mark(); if (!scanner.Find('}') || scanner.Position >= nextEolPos) { // not enclosed properly. return(null); } var attributesString = scanner.Extract(); if (string.IsNullOrWhiteSpace(attributesString)) { return(null); } // Position is on enclosing '}' (due to the Find('}'), so we have to skip 1 character end = scanner.Position + 1; return(attributesString.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s)).ToList()); }
internal static LinkDefinition ParseLinkDefinitionInternal(StringScanner p, bool extraMode) { // Skip leading white space p.SkipWhitespace(); // Must start with an opening square bracket if (!p.SkipChar('[')) return null; // Extract the id p.Mark(); if (!p.Find(']')) return null; var id = p.Extract(); if (id.Length == 0) return null; if (!p.SkipString("]:")) return null; // Parse the url and title var link = ParseLinkTarget(p, id, extraMode); // and trailing whitespace p.SkipLinespace(); // Trailing crap, not a valid link reference... if (!p.EndOfLine) return null; return link; }
internal static LinkDefinition ParseLinkDefinitionInternal(StringScanner p, bool ExtraMode) { // Skip leading white space p.SkipWhitespace(); // Must start with an opening square bracket if (!p.SkipChar('[')) { return(null); } // Extract the id p.Mark(); if (!p.Find(']')) { return(null); } string id = p.Extract(); if (id.Length == 0) { return(null); } if (!p.SkipString("]:")) { return(null); } // Parse the url and title var link = ParseLinkTarget(p, id, ExtraMode); // and trailing whitespace p.SkipLinespace(); // Trailing crap, not a valid link reference... if (!p.eol) { return(null); } return(link); }
private static HtmlTag ParseHelper(StringScanner p) { // Does it look like a tag? if (p.Current != '<') return null; // Skip '<' p.SkipForward(1); // Is it a comment? if (p.SkipString("!--")) { p.Mark(); if (p.Find("-->")) { var t = new HtmlTag("!"); t.m_attributes.Add("content", p.Extract()); t.m_closed = true; p.SkipForward(3); return t; } } // Is it a closing tag eg: </div> bool bClosing = p.SkipChar('/'); // Get the tag name string tagName=null; if (!p.SkipIdentifier(ref tagName)) return null; // Probably a tag, create the HtmlTag object now HtmlTag tag = new HtmlTag(tagName); tag.m_closing = bClosing; // If it's a closing tag, no attributes if (bClosing) { if (p.Current != '>') return null; p.SkipForward(1); return tag; } while (!p.Eof) { // Skip whitespace p.SkipWhitespace(); // Check for closed tag eg: <hr /> if (p.SkipString("/>")) { tag.m_closed=true; return tag; } // End of tag? if (p.SkipChar('>')) { return tag; } // attribute name string attributeName = null; if (!p.SkipIdentifier(ref attributeName)) return null; // Skip whitespace p.SkipWhitespace(); // Skip equal sign if (p.SkipChar('=')) { // Skip whitespace p.SkipWhitespace(); // Optional quotes if (p.SkipChar('\"')) { // Scan the value p.Mark(); if (!p.Find('\"')) return null; // Store the value tag.m_attributes.Add(attributeName, p.Extract()); // Skip closing quote p.SkipForward(1); } else { // Scan the value p.Mark(); while (!p.Eof && !char.IsWhiteSpace(p.Current) && p.Current != '>' && p.Current != '/') p.SkipForward(1); if (!p.Eof) { // Store the value tag.m_attributes.Add(attributeName, p.Extract()); } } } else { tag.m_attributes.Add(attributeName, ""); } } return null; }
private static HtmlTag ParseHelper(StringScanner p) { // Does it look like a tag? if (p.current != '<') { return(null); } // Skip '<' p.SkipForward(1); // Is it a comment? if (p.SkipString("!--")) { p.Mark(); if (p.Find("-->")) { var t = new HtmlTag("!"); t.m_attributes.Add("content", p.Extract()); t.m_closed = true; p.SkipForward(3); return(t); } } // Is it a closing tag eg: </div> bool bClosing = p.SkipChar('/'); // Get the tag name string tagName = null; if (!p.SkipIdentifier(ref tagName)) { return(null); } // Probably a tag, create the HtmlTag object now HtmlTag tag = new HtmlTag(tagName); tag.m_closing = bClosing; // If it's a closing tag, no attributes if (bClosing) { if (p.current != '>') { return(null); } p.SkipForward(1); return(tag); } while (!p.eof) { // Skip whitespace p.SkipWhitespace(); // Check for closed tag eg: <hr /> if (p.SkipString("/>")) { tag.m_closed = true; return(tag); } // End of tag? if (p.SkipChar('>')) { return(tag); } // attribute name string attributeName = null; if (!p.SkipIdentifier(ref attributeName)) { return(null); } // Skip whitespace p.SkipWhitespace(); // Skip equal sign if (p.SkipChar('=')) { // Skip whitespace p.SkipWhitespace(); // Optional quotes if (p.SkipChar('\"')) { // Scan the value p.Mark(); if (!p.Find('\"')) { return(null); } // Store the value tag.m_attributes.Add(attributeName, p.Extract()); // Skip closing quote p.SkipForward(1); } else { // Scan the value p.Mark(); while (!p.eof && !char.IsWhiteSpace(p.current) && p.current != '>' && p.current != '/') { p.SkipForward(1); } if (!p.eof) { // Store the value tag.m_attributes.Add(attributeName, p.Extract()); } } } else { tag.m_attributes.Add(attributeName, ""); } } return(null); }