private void WriteUnparsedTag(HtmlTag tag) { switch (tag.TagName) { case "%@": { // store directive for specialized parsing this.Directives.Append(tag.ToString()); break; } case "%!": { // analogous to static code, or JSP declarations // executed only on initialization of template // output from declarations are appended after the template this.Declarations.Append(tag.Content); break; } case "%#": // databinding expression { // unparsed expressions are emitted directly into JBST JbstUnparsedBlock code = new JbstUnparsedBlock(tag.Content); this.AppendChild(code); break; } case "%=": // inline expression { // expressions are emitted directly into JBST JbstExpressionBlock code = new JbstExpressionBlock(tag.Content); this.AppendChild(code); break; } case "%$": { // expressions are emitted directly into JBST JbstExtensionBlock code = new JbstExtensionBlock(tag.Content, this.path); this.AppendChild(code); break; } case "%": { // statements are emitted directly into JBST JbstStatementBlock code = new JbstStatementBlock(tag.Content); this.AppendChild(code); break; } case "%--": { // server-side comments are omitted even for debug break; } case "!--": { // HTML Comments are emitted directly into JBST JbstCommentBlock code = new JbstCommentBlock(tag.Content); this.AppendChild(code); break; } default: { // unrecognized sequences get emitted as encoded text this.AppendChild(tag.ToString()); break; } } }
private void WriteAttributes(HtmlTag tag) { foreach (KeyValuePair<string, object> attrib in tag.FilteredAttributes) { // normalize JBST command names string key = attrib.Key.StartsWith(JbstCommandBase.JbstPrefix, StringComparison.OrdinalIgnoreCase) ? attrib.Key.ToLowerInvariant() : attrib.Key; if (attrib.Value is string) { this.AddAttribute(attrib.Key, (string)attrib.Value); } else if (attrib.Value is HtmlTag) { HtmlTag codeVal = (HtmlTag)attrib.Value; switch (codeVal.TagName) { case "%@": { // store directive for specialized parsing this.Directives.Append(codeVal.ToString()); break; } case "%!": { // analogous to static code, or JSP declarations // executed only on initialization of template // output from declarations are appended after the template this.Declarations.Append(codeVal.Content); break; } case "%#": // databinding expression //{ // // unparsed expressions are emitted directly into JBST // JbstUnparsedBlock code = new JbstUnparsedBlock(codeVal.Content); // this.AddAttribute(key, code); // break; //} case "%=": // inline expression { // expressions are emitted directly into JBST JbstExpressionBlock code = new JbstExpressionBlock(codeVal.Content); this.AddAttribute(key, code); break; } case "%$": { // expressions are emitted directly into JBST JbstExtensionBlock code = new JbstExtensionBlock(codeVal.Content, this.path); this.AddAttribute(key, code); break; } case "%": { // statements are emitted directly into JBST JbstStatementBlock code = new JbstStatementBlock(codeVal.Content); this.AddAttribute(key, code); break; } case "%--": { // server-side comments are omitted even for debug break; } case "!--": { // HTML Comments are emitted directly into JBST // but get removed when minified JbstCommentBlock code = new JbstCommentBlock(codeVal.Content); this.AddAttribute(key, code); break; } default: { // unrecognized sequences get emitted as encoded text this.AddAttribute(key, codeVal.ToString()); break; } } } } }
private void WriteStyles(HtmlTag tag) { foreach (KeyValuePair<string, string> style in tag.FilteredStyles) { this.AddStyle(style.Key, style.Value); } }
private void RenderTag(HtmlTag tag) { try { if (this.htmlFilter == null || this.htmlFilter.FilterTag(tag)) { this.htmlWriter.WriteTag(tag); this.taxonomy |= tag.Taxonomy; } } catch (Exception ex) { try { this.WriteLiteral("[ERROR: "+ex.Message+"]"); } catch { } } }
void IHtmlWriter.WriteTag(HtmlTag tag) { switch (tag.TagType) { case HtmlTagType.Unparsed: { this.WriteUnparsedTag(tag); break; } case HtmlTagType.FullTag: case HtmlTagType.BeginTag: { this.PushTag(tag.RawName); if (tag.HasAttributes) { this.WriteAttributes(tag); } if (tag.HasStyles) { this.WriteStyles(tag); } if (tag.TagType == HtmlTagType.FullTag) { this.PopTag(tag.RawName); } break; } case HtmlTagType.EndTag: { this.PopTag(tag.RawName); break; } } }
private void RenderCloseTag(HtmlTag tag) { tag = tag.CreateCloseTag(); if (tag != null) { this.RenderTag(tag); } }
/// <summary> /// Attempts to parse the next sequence as a tag /// </summary> /// <returns>null if no tag was found (e.g. just LessThan char)</returns> private HtmlTag ParseTag() { HtmlTag tag = this.ParseBlocks(); if (tag != null) { return tag; } int i = 1; char ch = this.Peek(i); if (ch == EndTagChar) { i++; ch = this.Peek(i); } if (!IsNameStartChar(ch)) { // not a tag, treat as LessThan char return null; } while (IsNameChar(ch)) { i++; ch = this.Peek(i); } if (!Char.IsWhiteSpace(ch) && ch != EndTagChar && ch != CloseTagChar) { // not a tag, treat as LessThan char return null; } // remove tag open char this.EmptyBuffer(1); tag = new HtmlTag(this.FlushBuffer(i-1), this.htmlFilter); this.ParseSyncPoint(); this.ParseAttributes(tag); if (this.Current == CloseTagChar) { // remove GreaterThan char from source this.EmptyBuffer(1); } return tag; }
/// <summary> /// /// </summary> /// <param name="tag"></param> /// <param name="style"></param> private void ParseStyles(HtmlTag tag, string style) { string name, value; int start=0, i=0; while (i < style.Length) { name = value = String.Empty; // skip whitespace while (i < style.Length && Char.IsWhiteSpace(style, i)) { start = ++i; } // style name while (i < style.Length && style[i] != StylePropChar) { i++; } // copy style name if (start < style.Length) { name = style.Substring(start, i-start); } // inc first start = ++i; // skip whitespace while (i < style.Length && Char.IsWhiteSpace(style, i)) { // inc first start = ++i; } // style value while (i < style.Length && style[i] != StyleDelimChar) { // TODO: handle HTML entities (e.g. """) i++; } if (!String.IsNullOrEmpty(name) && start < style.Length) { // copy style value value = style.Substring(start, i-start); // apply style to tag tag.Styles[name.ToLowerInvariant()] = value; } // inc first start = ++i; } }
/// <summary> /// Parses for "unparsed blocks" (e.g. comments, code blocks) /// </summary> /// <returns>null if no comment found</returns> /// <param name="startDelim"></param> /// <param name="endDelim"></param> /// <remarks> /// This supports comments, DocType declarations, CDATA sections, and ASP/JSP-style blocks. /// </remarks> private HtmlTag ParseBlock(string startDelim, string endDelim) { int i=0; for (i=0; i<startDelim.Length; i++) { if (this.Peek(i) != startDelim[i]) { return null; } } // consume LessThan this.EmptyBuffer(1); string blockName = this.FlushBuffer(startDelim.Length-1); i = 0; while (!this.IsEOF) { if (this.Peek(i) == endDelim[i]) { i++; if (i == endDelim.Length) { break; } } else { i = 0; // add to comment contents this.Advance(); } } this.ParseSyncPoint(); string content = this.FlushBuffer(); if (!this.IsEOF) { this.EmptyBuffer(endDelim.Length); } HtmlTag unparsed = new HtmlTag(blockName, this.htmlFilter); if (!String.IsNullOrEmpty(content)) { unparsed.Content = content; } unparsed.EndDelim = endDelim.Substring(0, endDelim.Length-1); return unparsed; }
private void ParseAttributes(HtmlTag tag) { char ch = this.Current; while (!this.IsEOF && ch != CloseTagChar && ch != OpenTagChar) { string name = this.ParseAttributeName(); if (name.Length == 1 && name[0] == EndTagChar) { tag.SetFullTag(); name = String.Empty; } this.ParseSyncPoint(); object value = String.Empty; ch = this.Current; if (ch != CloseTagChar && ch != OpenTagChar) { // Get the value(if any) value = this.ParseAttributeValue(); } this.ParseSyncPoint(); if (!String.IsNullOrEmpty(name)) { if (value is String && HtmlTag.StyleAttrib.Equals(name, StringComparison.OrdinalIgnoreCase)) { this.ParseStyles(tag, value.ToString()); } else { tag.Attributes[name] = value; } } ch = this.Current; } }