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>Reads a "string" or a 'string' from the lexer. Delimiting can be done with a backslash.</summary> /// <param name="lexer">The lexer the string will be read from.</param> /// <param name="builder">The builder to read it into.</summary> public static void ReadString(MLLexer lexer, System.Text.StringBuilder builder) { lexer.Literal = true; char quote = lexer.Read(); char character = lexer.Read(); bool delimited = false; while (delimited || character != quote && character != StringReader.NULL) { if (character == '\\' && !delimited) { delimited = true; } else { delimited = false; builder.Append(character); } character = lexer.Read(); } // Exit literal mode: lexer.ExitLiteral(); }
public override void OnParseContent(MLLexer lexer){ lexer.Literal=true; // Keep reading until we hit </script>. StringBuilder codeText=new StringBuilder(); // Let the parser know what line it's really at: codeText.Append("\n#l"+(lexer.LineNumber-1)+"\n"); // Get the initial "empty" size: int size=codeText.Length; while(!AtEnd(lexer)){ codeText.Append(lexer.Read()); } // Great, good stuff. Add to the Document's code but only if this tag shouldn't be dumped: if(!Dump){ if(codeText.Length!=size){ Element.Document.AddCode(codeText.ToString()); } }else{ Wrench.Log.Add("Warning: Some script has been ignored due to it's type ('"+Element["type"]+"'). Did you mean 'text/nitro'?"); } lexer.Literal=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' ); }
/// <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' ); }
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)=='c'&& lexer.Peek(3)=='o'&& lexer.Peek(4)=='d' ); }
/// <summary>Skips any whitespaces that occur next in the given lexer.</summary> /// <param name="lexer">The lexer to skip spaces within.</param> public static void SkipSpaces(MLLexer lexer) { char peek = lexer.Peek(); while (peek == ' ') { lexer.Read(); peek = lexer.Peek(); } }
/// <summary>Sets the content of this language from a given xml string.</summary> /// <param name="content">An xml formatted string of all the variables in this language.</param> public void SetContent(string content) { if (content == null) { return; } // Parse content into our set of tags. // Look out for the <language> tag which provides our Name and Code. // Everything else should be <var> tags which must not fully parse the tree of their content. MLLexer lexer = new MLLexer(content); // Read the content into an element, which in turn will pass all its vars back up here. new LanguageElement(this, lexer); }
public override void OnParseContent(MLLexer lexer){ lexer.Literal=true; // Keep reading until we hit </style>. StringBuilder styleText=new StringBuilder(); while(!AtEnd(lexer)){ styleText.Append(lexer.Read()); } // Great, good stuff. Add to the document's style: if(styleText.Length!=0){ Element.Document.AddStyle(styleText.ToString()); } lexer.Literal=false; }
protected override MLElement CreateTagElement(MLLexer lexer){ // Only ever called at the top level - push the new child straight to the language set. LanguageElement result=new LanguageElement(Parent,lexer,true); if(result.Tag=="language"){ LanguageTag language=result.Handler as LanguageTag; language.Apply(Parent,result); }else{ // Must be a variable - if it isn't, error. VariableTag varTag=result.Handler as VariableTag; if(varTag==null){ throw new Exception("<"+result.Tag+"> not expected here - this file supports only <var>/<v> and <language> at it's top level (anything can go inside var/v though)."); } varTag.Parent=Parent; } return result; }
protected override MLElement CreateTagElement(MLLexer lexer) { // Only ever called at the top level - push the new child straight to the language set. LanguageElement result = new LanguageElement(Parent, lexer, true); if (result.Tag == "language") { LanguageTag language = result.Handler as LanguageTag; language.Apply(Parent, result); } else { // Must be a variable - if it isn't, error. VariableTag varTag = result.Handler as VariableTag; if (varTag == null) { throw new Exception("<" + result.Tag + "> not expected here - this file supports only <var>/<v> and <language> at it's top level (anything can go inside var/v though)."); } varTag.Parent = Parent; } return(result); }
/// <summary>Reads a tag from the given lexer. Note that this does not read it's children or closing tag.</summary> /// <param name="lexer">The lexer the tag should be read from.</param> protected void ReadTag(MLLexer lexer) { bool first = true; char peek = lexer.Peek(); if (peek == '<') { lexer.Read(); peek = lexer.Peek(); } while (peek != StringReader.NULL && peek != '>') { string property; string value; PropertyTextReader.Read(lexer, first || SelfClosing, out property, out value); property = property.ToLower(); if (first) { first = false; SetTag(property); } else if (property == "/") { SelfClosing = true; } else { this[property] = value; } peek = lexer.Peek(); } if (peek == '>') { lexer.Read(); } }
/// <summary>Called from within this element to generate a new tag element.</summary> protected virtual MLElement CreateTagElement(MLLexer lexer) { return(null); }
/// <summary>Reads the children for this tag from a lexer.</summary> /// <param name="lexer"></param> /// <param name="innerElement">True if we're looking for the closing tag of this element to exit. /// If its found, this method safely returns. Unbalanced tags will otherwise throw an exception.</param> /// <param name="literal">Literal is true if the content should be read 'as is', ignoring any tags.</param> protected void ReadContent(MLLexer lexer, bool innerElement, bool literal) { char Peek = lexer.Peek(); string variableString = ""; bool readingVariable = false; MLTextElement textElement = null; List <string> variableArguments = null; System.Text.StringBuilder builder = new System.Text.StringBuilder(); while (Peek != StringReader.NULL) { if (readingVariable) { lexer.Read(); if (Peek == ';') { readingVariable = false; // First, flush textElement if we're working on one (likely): if (textElement != null) { // Make sure it adds the last word: textElement.DoneWord(true); textElement = null; } if (builder.Length != 0) { // The name is in the builder: variableString = builder.ToString(); builder.Length = 0; } // Check if this string (e.g. &WelcomeMessage;) is provided by the variable set: // Generate a new variable element: MLVariableElement varElement = CreateVariableElement(); varElement.SetVariableName(variableString); if (variableArguments != null) { varElement.SetArguments(variableArguments.ToArray()); variableArguments = null; } varElement.LoadNow(innerElement); variableString = ""; } else if (Peek == '(') { // Read runtime argument set. &WelcomeMessage('heya!'); variableString = builder.ToString(); builder.Length = 0; Peek = lexer.Peek(); variableArguments = new List <string>(); while (Peek != StringReader.NULL) { if (Peek == ')') { // Add it: variableArguments.Add(builder.ToString()); builder.Length = 0; // Read it off: lexer.Read(); break; } else if (Peek == ',') { // Done one parameter - onto the next. variableArguments.Add(builder.ToString()); builder.Length = 0; } else if (Peek == '"' || Peek == '\'') { // One of our args is a "string". // Use the string reader of the PropertyTextReader to read it. PropertyTextReader.ReadString(lexer, builder); // We don't want to read a char off, so continue here. // Peek the next one: Peek = lexer.Peek(); continue; } else if (Peek != ' ') { // Generall numeric args will fall down here. // Disallowing spaces means the set can be spaced out like so: (14, 21) builder.Append(Peek); } // Read off the char: lexer.Read(); // Peek the next one: Peek = lexer.Peek(); } } else { builder.Append(Peek); } } else if (!literal && Peek == '<') { if (textElement != null) { // Make sure it adds the last word: textElement.DoneWord(true); textElement = null; } // Read off the <. lexer.Read(); if (lexer.Peek() == '/') { // Should be the closure (</tag>) for 'this' element. // Read off the /: lexer.Read(); char closePeek = lexer.Peek(); while (closePeek != '>' && closePeek != StringReader.NULL) { builder.Append(closePeek); lexer.Read(); closePeek = lexer.Peek(); } string tag = builder.ToString(); builder.Length = 0; if (closePeek == '>') { // Read it off: lexer.Read(); } if (innerElement && (tag == Tag || tag.ToLower() == Tag)) { // Closure for this element read off. // Time to get outta here! return; } else { int charNumber; int line = lexer.GetLineNumber(out charNumber); throw new Exception("Unbalanced tags detected: " + tag + " is closing " + Tag + " at line " + line + ", character " + charNumber + ". " + lexer.ReadLine(line) + "."); } } else { MLElement tag = CreateTagElement(lexer); TagHandler handler = tag.GetHandler(); if (tag.SelfClosing) { tag.OnChildrenLoaded(); handler.OnTagLoaded(); } else { handler.OnParseContent(lexer); // Read its kids and possibly its ending tag (the true means we're expecting an ending tag): tag.ReadContent(lexer, true, false); tag.OnChildrenLoaded(); handler.OnTagLoaded(); } } } else if (!literal && Peek == '&') { // E.g. > & etc. readingVariable = true; // Read off the &: lexer.Read(); } else { if (textElement == null) { textElement = CreateTextElement(); } textElement.AddCharacter(lexer.Read()); } Peek = lexer.Peek(); } if (textElement != null) { textElement.DoneWord(true); } }
public LanguageElement(LanguageSet parent, MLLexer lexer, bool innerElement) { Parent = parent; ReadTag(lexer); }
public LanguageElement(LanguageSet parent, MLLexer lexer) { Parent = parent; // This is the 'top' tag - start reading it's content. ReadContent(lexer, false, false); }
/// <summary>Reads a property and its value from the given lexer.</summary> /// <param name="lexer">The lexer to read the property from.</param> /// <param name="selfClosing">True if the tag being read is a self closing one.</param> /// <param name="property">The name of the property that was read.</param> /// <param name="value">The value of the property, if there was one. Null otherwise.</param> public static void Read(MLLexer lexer, bool selfClosing, out string property, out string value) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); SkipSpaces(lexer); char peek = lexer.Peek(); while (peek != StringReader.NULL && peek != ' ' && peek != '=' && peek != '>' && (peek != '/' || builder.Length == 0)) { builder.Append(char.ToLower(lexer.Read())); peek = lexer.Peek(); } // Get the property: property = builder.ToString(); // Clear it: builder.Length = 0; SkipSpaces(lexer); peek = lexer.Peek(); if (peek == '=') { // Here comes the value! lexer.Read(); SkipSpaces(lexer); peek = lexer.Peek(); if (peek == StringReader.NULL) { value = builder.ToString(); return; } else if (peek == '"' || peek == '\'') { ReadString(lexer, builder); } else { char character = lexer.Peek(); // Read until we hit a space. while (character != ' ' && character != '>') { if (character == '/' && lexer.Peek(1) == '>') { // End only if this is a self-closing tag. if (selfClosing) { value = builder.ToString(); return; } } lexer.Read(); builder.Append(character); character = lexer.Peek(); if (lexer.DidReadJunk) { break; } } } } SkipSpaces(lexer); value = builder.ToString(); }
/// <summary>Generates a new html element.</summary> /// <returns>A new html element.</returns> protected override MLElement CreateTagElement(MLLexer lexer){ Element tag=new Element(Document,lexer,this); if(tag.Handler!=null && tag.Handler.Junk()){ // Junk tag - prevent it entering the DOM. return tag; } AppendNewChild(tag); return tag; }
/// <summary>Appends the given html text to the content of this element.</summary> /// <param name="text">The html text to append.</param> public void appendInnerHTML(string text){ if(string.IsNullOrEmpty(text)){ return; } MLLexer lexer=new MLLexer(text); ReadContent(lexer,false,false); }
//--------------------------------------
/// <summary>Reads a "string" or a 'string' from the lexer. Delimiting can be done with a backslash.</summary> /// <param name="lexer">The lexer the string will be read from.</param> /// <param name="builder">The builder to read it into.</summary> public static void ReadString(MLLexer lexer,System.Text.StringBuilder builder){ lexer.Literal=true; char quote=lexer.Read(); char character=lexer.Read(); bool delimited=false; while(delimited||character!=quote&&character!=StringReader.NULL){ if(character=='\\'&&!delimited){ delimited=true; }else{ delimited=false; builder.Append(character); } character=lexer.Read(); } // Exit literal mode: lexer.ExitLiteral(); }
/// <summary>Reads a property and its value from the given lexer.</summary> /// <param name="lexer">The lexer to read the property from.</param> /// <param name="selfClosing">True if the tag being read is a self closing one.</param> /// <param name="property">The name of the property that was read.</param> /// <param name="value">The value of the property, if there was one. Null otherwise.</param> public static void Read(MLLexer lexer,bool selfClosing,out string property,out string value){ System.Text.StringBuilder builder=new System.Text.StringBuilder(); SkipSpaces(lexer); char peek=lexer.Peek(); while(peek!=StringReader.NULL&&peek!=' '&&peek!='='&&peek!='>'&&(peek!='/'||builder.Length==0)){ builder.Append(char.ToLower(lexer.Read())); peek=lexer.Peek(); } // Get the property: property=builder.ToString(); // Clear it: builder.Length=0; SkipSpaces(lexer); peek=lexer.Peek(); if(peek=='='){ // Here comes the value! lexer.Read(); SkipSpaces(lexer); peek=lexer.Peek(); if(peek==StringReader.NULL){ value=builder.ToString(); return; }else if(peek=='"'||peek=='\''){ ReadString(lexer,builder); }else{ char character=lexer.Peek(); // Read until we hit a space. while(character!=' ' && character!='>'){ if(character=='/' && lexer.Peek(1)=='>'){ // End only if this is a self-closing tag. if(selfClosing){ value=builder.ToString(); return; } } lexer.Read(); builder.Append(character); character=lexer.Peek(); if(lexer.DidReadJunk){ break; } } } } SkipSpaces(lexer); value=builder.ToString(); }
/// <summary>Skips any whitespaces that occur next in the given lexer.</summary> /// <param name="lexer">The lexer to skip spaces within.</param> public static void SkipSpaces(MLLexer lexer){ char peek=lexer.Peek(); while(peek==' '){ lexer.Read(); peek=lexer.Peek(); } }
/// <summary>Creates a new element for the given document and as a child of the given parent with content to parse.</summary> /// <param name="document">The document that this element will belong to.</param> /// <param name="lexer">An MLLexer containing the tag. No children are read; Just this tag only.</param> /// <param name="parent">The element that this element will be parented to.</param> private Element(Document document,MLLexer lexer,Element parent):this(document,parent){ ReadTag(lexer); }
/// <summary>Appends the given literal text to the content of this element. /// This is good for preventing html injection as the text will be taken literally.</summary> /// <param name="text">The literal text to append.</param> public void appendTextContent(string text){ if(string.IsNullOrEmpty(text)){ return; } MLLexer lexer=new MLLexer(text,true); ReadContent(lexer,false,true); }
public LanguageElement(LanguageSet parent,MLLexer lexer){ Parent=parent; // This is the 'top' tag - start reading it's content. ReadContent(lexer,false,false); }
public LanguageElement(LanguageSet parent,MLLexer lexer,bool innerElement){ Parent=parent; ReadTag(lexer); }
public override void OnParseContent(MLLexer lexer){ lexer.Literal=true; // Keep reading until we hit </textarea>. StringBuilder valueText=new StringBuilder(); while(!AtEnd(lexer)){ valueText.Append(lexer.Read()); } // Assign to the value: SetValue(valueText.ToString()); lexer.Literal=false; }