/// <summary>Attempts to read a block comment from the given lexer.</summary> /// <param name="lexer">The lexer to read it from.</param> /// <param name="currentCharacter">The next character in the lexer.</param> /// <returns>True if a block comment was read.</returns> private bool TryReadBlockComment(MLLexer lexer, char currentCharacter) { if (currentCharacter == '/' && lexer.Peek(1) == '*') { // CSS block comment. lexer.Read(); lexer.Read(); currentCharacter = lexer.Peek(); while (currentCharacter != StringReader.NULL) { if (currentCharacter == '*' && lexer.Peek(1) == '/') { //all done! lexer.Read(); lexer.Read(); break; } lexer.Read(); currentCharacter = lexer.Peek(); } return(true); } return(false); }
/// <summary>Checks if the given lexer has reached the end of the inline style content.</summary> /// <param name="lexer">The lexer to check if it's reached the </style> tag.</param> /// <returns>True if the lexer has reached the end style tag; false otherwise.</returns> private bool AtEnd(MLLexer lexer) { // Up to y will do; we're certainly at the end by that point. return(lexer.Peek() == '<' && lexer.Peek(1) == '/' && lexer.Peek(2) == 's' && lexer.Peek(3) == 't' && lexer.Peek(4) == 'y' ); }
protected override bool AtEnd(MLLexer lexer) { // Three will do; we're certainly at the end by that point. return(lexer.Peek() == '<' && lexer.Peek(1) == '/' && lexer.Peek(2) == 's' && lexer.Peek(3) == 'a' && lexer.Peek(4) == 'm' ); }
/// <summary>Checks if the given lexer has reached the end of the inline pre content.</summary> /// <param name="lexer">The lexer to check if it's reached the </pre> tag.</param> /// <returns>True if the lexer has reached the end pre tag; false otherwise.</returns> protected virtual bool AtEnd(MLLexer lexer) { // Three will do; we're certainly at the end by that point. return(lexer.Peek() == '<' && lexer.Peek(1) == '/' && lexer.Peek(2) == 'p' && lexer.Peek(3) == 'r' && lexer.Peek(4) == 'e' ); }
public override void OnParseContent(MLLexer lexer) { lexer.Literal = true; // Keep reading until we hit </pre>. StringBuilder text = new StringBuilder(); while (!AtEnd(lexer)) { char read = lexer.Read(); // Convert any newlines into <br>eaks. if (read == '\r') { if (lexer.Peek() == '\n') { // It will handle the \n instead. continue; } text.Append("<br>"); } else if (read == '<') { text.Append(">"); } else if (read == '&') { text.Append("&"); } else if (read == '\n') { text.Append("<br>"); } else { text.Append(read); } } // Great, good stuff! Apply to its text content (literally): if (text.Length != 0) { Element.innerHTML = text.ToString(); } lexer.Literal = false; }
/// <summary>Checks if the given lexer is at the end of the variable tag currently being parsed.</summary> /// <param name="lexer">The lexer to check.</param> /// <returns>True if the lexer is now at the end of the variable tags content; false otherwise.</returns> private bool AtEnd(MLLexer lexer) { if (lexer.Peek() == '<' && lexer.Peek(1) == '/' && lexer.Peek(2) == 'v') { if (lexer.Peek(3) == '>' || (lexer.Peek(3) == 'a' && lexer.Peek(4) == 'r')) { return(true); } } return(false); }
/// <summary>Keeps reading selectors and their properties until a > or the end of the css is reached.</summary> /// <param name="css">The css text to parse.</param> public void ParseCss(string css) { MLLexer lexer = new MLLexer(css); char currentCharacter = lexer.Peek(); while (currentCharacter != '<' && currentCharacter != StringReader.NULL) { if (TryReadBlockComment(lexer, currentCharacter)) { currentCharacter = lexer.Peek(); continue; } // Read a selector: string selector = ""; string modifier = ""; bool inModifier = false; List <Selector> additionalSelectors = null; while (currentCharacter != '{' && currentCharacter != '<' && currentCharacter != StringReader.NULL) { // Read it off: lexer.Read(); if (currentCharacter == ' ') { // Skip spaces here. } else if (currentCharacter == ',') { // We have a series of selectors. if (selector != "") { // Store the current one in the additional list: if (additionalSelectors == null) { additionalSelectors = new List <Selector>(1); } additionalSelectors.Add(new Selector(this, selector, modifier)); // Clear the current one: selector = ""; modifier = ""; inModifier = false; } } else if (currentCharacter == ':') { if (inModifier) { // Already in the modifier - they've been daisy chained. // So, the modifier we've read so far is actually part of the selector: selector += ":" + modifier.ToLower(); modifier = ""; } inModifier = true; } else if (inModifier) { // Add it to the modifier: modifier += currentCharacter; } else { // Add it to the selector: selector += currentCharacter; } // Peek the next one: currentCharacter = lexer.Peek(); } if (currentCharacter == '{') { // Read it off: lexer.Read(); } else { // It must have been a < or null. Halt. break; } // Start the style block: SelectorStyle style = StartSelector(selector, modifier); // Read the properties inside a selectors block. Literal reading after : until ; bool readPropertyName = true; string propertyName = ""; string propertyValue = ""; currentCharacter = lexer.Peek(); while (currentCharacter != '}' && currentCharacter != '<' && currentCharacter != StringReader.NULL) { if (readPropertyName) { if (TryReadBlockComment(lexer, currentCharacter)) { currentCharacter = lexer.Peek(); continue; } if (currentCharacter == ':') { // Bump into literal mode. lexer.Literal = true; readPropertyName = false; } else { propertyName += currentCharacter; } } else { if (currentCharacter == ';') { // Pop out of literal mode, and go back to property names. readPropertyName = true; lexer.Literal = false; // And push our new propertyName/propertyValue set: style.SetDirect(propertyName, propertyValue); if (additionalSelectors != null) { // We have more,than,one selector. // Set to them too: for (int i = additionalSelectors.Count - 1; i >= 0; i--) { additionalSelectors[i].Style.SetDirect(propertyName, propertyValue); } } propertyName = ""; propertyValue = ""; } else { propertyValue += currentCharacter; } } // Read it off: lexer.Read(); // And take a look at what's next: currentCharacter = lexer.Peek(); } // Let the style know it's done loading: style.OnLoaded(); // 'Bake' the new styles into their modified forms, if any have been loaded yet. style.BakeToModifiers(); if (additionalSelectors != null) { // We have more,than,one selector. // Start their blocks too: for (int i = additionalSelectors.Count - 1; i >= 0; i--) { additionalSelectors[i].Style.BakeToModifiers(); } } if (currentCharacter == '}') { // Read it off: lexer.Read(); // And setup the next character: currentCharacter = lexer.Peek(); } else { // Halt - it was a null or <. break; } // Ensure we're out of literal mode: lexer.Literal = false; } }
//--------------------------------------