private static bool TryParseHtmlTagHtmlComment(ref StringSlice text, ref ValueStringBuilder builder) { var c = text.NextChar(); if (c != '-') { return(false); } builder.Append('-'); builder.Append('-'); if (text.PeekChar() == '>') { return(false); } var countHyphen = 0; while (true) { c = text.NextChar(); if (c == '\0') { return(false); } if (countHyphen == 2) { if (c == '>') { builder.Append('>'); text.SkipChar(); return(true); } return(false); } countHyphen = c == '-' ? countHyphen + 1 : 0; builder.Append(c); } }
private static bool TryParseHtmlTag(ref StringSlice text, ref ValueStringBuilder builder) { var c = text.CurrentChar; if (c != '<') { return(false); } c = text.NextChar(); builder.Append('<'); switch (c) { case '/': return(TryParseHtmlCloseTag(ref text, ref builder)); case '?': return(TryParseHtmlTagProcessingInstruction(ref text, ref builder)); case '!': builder.Append(c); c = text.NextChar(); if (c == '-') { return(TryParseHtmlTagHtmlComment(ref text, ref builder)); } if (c == '[') { return(TryParseHtmlTagCData(ref text, ref builder)); } return(TryParseHtmlTagDeclaration(ref text, ref builder)); } return(TryParseHtmlTagOpenTag(ref text, ref builder)); }
internal static bool TryParseHtmlTagOpenTag(ref StringSlice text, ref ValueStringBuilder builder) { var c = text.CurrentChar; // Parse the tagname if (!c.IsAlpha()) { return(false); } builder.Append(c); while (true) { c = text.NextChar(); if (c.IsAlphaNumeric() || c == '-') { builder.Append(c); } else { break; } } bool hasAttribute = false; while (true) { var hasWhitespaces = false; // Skip any whitespaces while (c.IsWhitespace()) { builder.Append(c); c = text.NextChar(); hasWhitespaces = true; } switch (c) { case '\0': return(false); case '>': text.SkipChar(); builder.Append(c); return(true); case '/': builder.Append('/'); c = text.NextChar(); if (c != '>') { return(false); } text.SkipChar(); builder.Append('>'); return(true); case '=': if (!hasAttribute) { return(false); } builder.Append('='); // Skip any spaces after c = text.NextChar(); while (c.IsWhitespace()) { builder.Append(c); c = text.NextChar(); } // Parse a quoted string if (c == '\'' || c == '\"') { builder.Append(c); char openingStringChar = c; while (true) { c = text.NextChar(); if (c == '\0') { return(false); } if (c != openingStringChar) { builder.Append(c); } else { break; } } builder.Append(c); c = text.NextChar(); } else { // Parse until we match a space or a special html character int matchCount = 0; while (true) { if (c == '\0') { return(false); } if (c == ' ' || c == '\n' || c == '"' || c == '\'' || c == '=' || c == '<' || c == '>' || c == '`') { break; } matchCount++; builder.Append(c); c = text.NextChar(); } // We need at least one char after '=' if (matchCount == 0) { return(false); } } hasAttribute = false; continue; default: if (!hasWhitespaces) { return(false); } // Parse the attribute name if (!(c.IsAlpha() || c == '_' || c == ':')) { return(false); } builder.Append(c); while (true) { c = text.NextChar(); if (c.IsAlphaNumeric() || c == '_' || c == ':' || c == '.' || c == '-') { builder.Append(c); } else { break; } } hasAttribute = true; break; } } }
private static bool TryParseHtmlTagProcessingInstruction(ref StringSlice text, ref ValueStringBuilder builder) { builder.Append('?'); var prevChar = '\0'; while (true) { var c = text.NextChar(); if (c == '\0') { return(false); } if (c == '>' && prevChar == '?') { builder.Append('>'); text.SkipChar(); return(true); } prevChar = c; builder.Append(c); } }