Ejemplo n.º 1
0
 public MetalUseMacro(Tag tag, string expression, Dictionary<string, ProgramSlot> slots, List<MetalDefineParam> parameters)
     : base(tag, CommandType.MetalUseMacro)
 {
     Expression = expression;
     Slots = slots;
     Parameters = parameters;
 }
Ejemplo n.º 2
0
 public MetalDefineParam(Tag tag, string type, string name, string expression)
     : base(tag, CommandType.MetalDefineParam)
 {
     Type = type;
     Name = name;
     Expression = expression;
 }
Ejemplo n.º 3
0
 public TalDefine(Tag tag, VariableScope scope, string name, string expression)
     : base(tag, CommandType.TalDefine)
 {
     Scope = scope;
     Name = name;
     Expression = expression;
 }
Ejemplo n.º 4
0
 public Tag(Tag tag)
 {
     Name = tag.Name;
     Suffix = tag.Suffix;
     Singleton = tag.Singleton;
     if (tag.Attributes != null)
         Attributes = new List<TagAttribute>(tag.Attributes);
     SourcePath = tag.SourcePath;
     LineNumber = tag.LineNumber;
     LinePosition = tag.LinePosition;
 }
Ejemplo n.º 5
0
 public TalRepeat(Tag tag, string name, string expression)
     : base(tag, CommandType.TalRepeat)
 {
     Name = name;
     Expression = expression;
 }
Ejemplo n.º 6
0
 public TalReplace(Tag tag, string expression, bool structure)
     : base(tag, CommandType.TalReplace)
 {
     Structure = structure;
     Expression = expression;
 }
Ejemplo n.º 7
0
        TagStackItem AddTagToStack(Tag tag, List<TagAttribute> cleanAttributes)
        {
            // Set tag attributes to contain only normal HTML/XML attributes (TAL/METAL attributes are removed)
            tag.Attributes = cleanAttributes;

            // Add tag to tag stack
            var tagStackItem = new TagStackItem(tag);
            _tagStack.Add(tagStackItem);
            return tagStackItem;
        }
Ejemplo n.º 8
0
        protected override void HandleEndTag(Tag tag)
        {
            while (_tagStack.Count > 0)
            {
                TagStackItem tagStackItem = _tagStack.Last();
                _tagStack.RemoveAt(_tagStack.Count - 1);

                Tag oldTag = tagStackItem.Tag;

                int? endTagCommandLocation = tagStackItem.EndTagCommandLocation;
                List<Action> popFunctionList = tagStackItem.PopFunctionList;

                if (popFunctionList != null)
                {
                    foreach (Action func in popFunctionList)
                        func();
                }

                if (oldTag.Name == tag.Name)
                {
                    // We've found the right tag, now check to see if we have any TAL commands on it
                    if (endTagCommandLocation != null)
                    {
                        // We have a command (it's a TAL tag)
                        // Note where the end tag command location should point (i.e. the next command)
                        _endTagsCommandMap[(int)endTagCommandLocation] = _programCommands.Count;

                        // We need a "close scope and tag" command
                        _programCommands.Add(new CmdEndTagEndScope(tag));
                        return;
                    }
                    if (!tag.Singleton)
                    {
                        // We are popping off an un-interesting tag, just add the close as text
                        _programCommands.Add(new CmdOutput(tag, "</" + tag.Name + ">"));
                        return;
                    }
                    // We are suppressing the output of this tag, so just return
                    return;
                }

                // We have a different tag, which means something like <br> which never closes is in
                // between us and the real tag.

                // If the tag that we did pop off has a command though it means un-balanced TAL tags!
                if (endTagCommandLocation != null)
                {
                    // ERROR
                    string msg = string.Format("TAL/METAL Elements must be balanced - found close tag {0} expecting {1}", tag.Name, oldTag.Name);
                    throw new TemplateParseException(oldTag, msg);
                }
            }
            throw new TemplateParseException(null,
                string.Format("</{0}> {1}", tag.Name, "Close tag encountered with no corresponding open tag."));
        }
Ejemplo n.º 9
0
 public MetalDefineSlot(Tag tag, string slotName)
     : base(tag, CommandType.MetalDefineSlot)
 {
     SlotName = slotName;
 }
Ejemplo n.º 10
0
 public TalAttributes(Tag tag, List<TagAttribute> attributes)
     : base(tag, CommandType.TalAttributes)
 {
     Attributes = attributes;
 }
Ejemplo n.º 11
0
 public MetaInterpolation(Tag tag, bool enabled)
     : base(tag, CommandType.MetaInterpolation)
 {
     Enabled = enabled;
 }
Ejemplo n.º 12
0
 public CmdStartScope(Tag tag)
     : base(tag, CommandType.CmdStartScope)
 {
 }
Ejemplo n.º 13
0
 public TalCondition(Tag tag, string expression)
     : base(tag, CommandType.TalCondition)
 {
     Expression = expression;
 }
Ejemplo n.º 14
0
 public CmdOutput(Tag tag, string data)
     : base(tag, CommandType.CmdOutput)
 {
     Data = data;
 }
Ejemplo n.º 15
0
 public TalOmitTag(Tag tag, string expression)
     : base(tag, CommandType.TalOmittag)
 {
     Expression = expression;
 }
Ejemplo n.º 16
0
 public CmdEndTagEndScope(Tag tag)
     : base(tag, CommandType.CmdEndtagEndscope)
 {
 }
Ejemplo n.º 17
0
 public TalContent(Tag tag, string expression, bool structure)
     : base(tag, CommandType.TalContent)
 {
     Structure = structure;
     Expression = expression;
 }
Ejemplo n.º 18
0
 public TagStackItem(Tag tag)
 {
     Tag = tag;
     EndTagCommandLocation = null;
     PopFunctionList = null;
     UseMacroCommandLocation = -1;
 }
 protected abstract void HandleEndTag(Tag tag);
Ejemplo n.º 20
0
        protected override void HandleStartTag(Tag tag)
        {
            // Note down the tag we are handling, it will be used for error handling during compilation
            _currentStartTag = new Tag(tag);

            // Expand HTML entity references in attribute values
            foreach (TagAttribute att in _currentStartTag.Attributes)
                att.Value = att.UnescapedValue;

            // Sorted dictionary of TAL attributes grouped by attribute type. The dictionary is sorted by the attribute type.
            SortedDictionary<CommandType, List<TagAttribute>> talAttributesDictionary = new SortedDictionary<CommandType, List<TagAttribute>>(new CommandTypeComparer());
            // Clean HTML/XML attributes
            var cleanAttributes = new List<TagAttribute>();
            var popFunctionList = new List<Action>();
            bool isTalElementNameSpace = false;
            string prefixToAdd = "";

            // Resolve TAL/METAL namespace declarations from attributes
            foreach (var att in _currentStartTag.Attributes)
            {
                if (att.Name.Length > 4 && att.Name.Substring(0, 5) == "xmlns")
                {
                    // We have a namespace declaration.
                    string prefix = att.Name.Length > 5 ? att.Name.Substring(6) : "";
                    if (att.Value == Namespaces.MetaNs)
                    {
                        // It's a META namespace declaration
                        if (prefix.Length > 0)
                        {
                            _metaNamespacePrefixStack.Add(_metaNamespacePrefix);
                            SetMetaPrefix(prefix);
                            // We want this function called when the scope ends
                            popFunctionList.Add(PopMetaNamespace);
                        }
                        else
                        {
                            // We don't allow META/METAL/TAL to be declared as a default
                            const string msg = "Can not use META name space by default, a prefix must be provided.";
                            throw new TemplateParseException(_currentStartTag, msg);
                        }
                    }
                    else if (att.Value == Namespaces.MetalNs)
                    {
                        // It's a METAL namespace declaration
                        if (prefix.Length > 0)
                        {
                            _metalNamespacePrefixStack.Add(_metalNamespacePrefix);
                            SetMetalPrefix(prefix);
                            // We want this function called when the scope ends
                            popFunctionList.Add(PopMetalNamespace);
                        }
                        else
                        {
                            // We don't allow META/METAL/TAL to be declared as a default
                            const string msg = "Can not use METAL name space by default, a prefix must be provided.";
                            throw new TemplateParseException(_currentStartTag, msg);
                        }
                    }
                    else if (att.Value == Namespaces.TalNs)
                    {
                        // TAL this time
                        if (prefix.Length > 0)
                        {
                            _talNamespacePrefixStack.Add(_talNamespacePrefix);
                            SetTalPrefix(prefix);
                            // We want this function called when the scope ends
                            popFunctionList.Add(PopTalNamespace);
                        }
                        else
                        {
                            // We don't allow META/METAL/TAL to be declared as a default
                            const string msg = "Can not use TAL name space by default, a prefix must be provided.";
                            throw new TemplateParseException(_currentStartTag, msg);
                        }
                    }
                    else
                    {
                        // It's nothing special, just an ordinary namespace declaration
                        cleanAttributes.Add(att);
                    }
                }
            }

            // Determine whether this element is in either the METAL or TAL namespace
            if (tag.Name.IndexOf(':') > 0)
            {
                // We have a namespace involved, so let's look to see if its one of ours
                string _namespace = tag.Name.Substring(0, tag.Name.IndexOf(':'));
                if (_namespace == _metalNamespacePrefix)
                {
                    isTalElementNameSpace = true;
                    prefixToAdd = _metalNamespacePrefix + ":";
                }
                else if (_namespace == _talNamespacePrefix)
                {
                    isTalElementNameSpace = true;
                    prefixToAdd = _talNamespacePrefix + ":";
                }
                if (isTalElementNameSpace)
                {
                    // We should treat this an implicit omit-tag
                    // Will go to default, i.e. yes
                    talAttributesDictionary[CommandType.TalOmittag] = new List<TagAttribute> { new TalTagAttribute { Value = "", CommandType = CommandType.TalOmittag } };
                }
            }

            // Look for TAL/METAL attributes
            foreach (var att in _currentStartTag.Attributes)
            {
                if (att.Name.Length > 4 && att.Name.Substring(0, 5) == "xmlns")
                    // We have a namespace declaration.
                    continue;

                string talCommandName;

                if (isTalElementNameSpace && att.Name.IndexOf(':') < 0)
                    // This means that the attribute name does not have a namespace, so use the prefix for this tag.
                    talCommandName = prefixToAdd + att.Name;
                else
                    talCommandName = att.Name;

                if (_talAttributeMap.ContainsKey(talCommandName))
                {
                    // It's a TAL attribute
                    CommandType cmdType = _talAttributeMap[talCommandName];
                    if (cmdType == CommandType.TalOmittag && isTalElementNameSpace)
                    {
                        // Supressing omit-tag command present on TAL or METAL element
                    }
                    else
                    {
                        if (!talAttributesDictionary.ContainsKey(cmdType))
                            talAttributesDictionary.Add(cmdType, new List<TagAttribute>());
                        talAttributesDictionary[cmdType].Add(new TalTagAttribute(att) { CommandType = cmdType });
                    }
                }
                else if (_metalAttributeMap.ContainsKey(talCommandName))
                {
                    // It's a METAL attribute
                    CommandType cmdType = _metalAttributeMap[talCommandName];
                    if (!talAttributesDictionary.ContainsKey(cmdType))
                        talAttributesDictionary.Add(cmdType, new List<TagAttribute>());
                    talAttributesDictionary[cmdType].Add(new TalTagAttribute(att) { CommandType = cmdType });
                }
                else if (_metaAttributeMap.ContainsKey(talCommandName))
                {
                    // It's a META attribute
                    CommandType cmdType = _metaAttributeMap[talCommandName];
                    if (!talAttributesDictionary.ContainsKey(cmdType))
                        talAttributesDictionary.Add(cmdType, new List<TagAttribute>());
                    talAttributesDictionary[cmdType].Add(new TalTagAttribute(att) { CommandType = cmdType });
                }
                else
                {
                    // It's normal HTML/XML attribute
                    cleanAttributes.Add(att);
                }
            }

            if (cleanAttributes.Count > 0)
            {
                // Insert normal HTML/XML attributes BEFORE other TAL/METAL TAL_ATTRIBUTES commands
                // as fake TAL_ATTRIBUTES commands to enable string expressions interpolation on normal HTML/XML attributes.
                if (!talAttributesDictionary.ContainsKey(CommandType.TalAttributes))
                    talAttributesDictionary.Add(CommandType.TalAttributes, new List<TagAttribute>());
                talAttributesDictionary[CommandType.TalAttributes].InsertRange(0, cleanAttributes);
            }

            // Create a symbol for the end of the tag - we don't know what the offset is yet
            _endTagCommandLocationCounter++;

            TagStackItem tagStackItem = null;
            foreach (CommandType cmdType in talAttributesDictionary.Keys)
            {
                // Resolve program commands from tal attributes
                var commands = _talAttributeHandlers[cmdType](talAttributesDictionary[cmdType]);
                if (commands != null)
                    foreach (Command cmd in commands)
                    {
                        if (tagStackItem == null)
                        {
                            // The first command needs to add the tag to the tag stack
                            tagStackItem = AddTagToStack(tag, cleanAttributes);

                            // Save metal:use-macro command position
                            if (cmd.CommandType == CommandType.MetalUseMacro)
                                tagStackItem.UseMacroCommandLocation = _programCommands.Count + 1;

                            // Append command to create new scope for the tag
                            Command startScopeCmd = new CmdStartScope(_currentStartTag);
                            _programCommands.Add(startScopeCmd);
                        }

                        // All others just append
                        _programCommands.Add(cmd);
                    }
            }

            if (tagStackItem == null)
            {
                tagStackItem = AddTagToStack(tag, cleanAttributes);

                // Append command to create new scope for the tag
                _programCommands.Add(new CmdStartScope(_currentStartTag));
            }

            // Save pop functions and end tag command location for this tag
            tagStackItem.PopFunctionList = popFunctionList;
            tagStackItem.EndTagCommandLocation = _endTagCommandLocationCounter;

            // Finally, append start tag command
            _programCommands.Add(new CmdStartTag(_currentStartTag));
        }
 protected abstract void HandleStartTag(Tag tag);
Ejemplo n.º 22
0
        Program GetTemplateProgram(string templateBody, string templatePath)
        {
            // Init per-template-body compiling state
            _importMacroCommands = new HashSet<string>();

            // Try to get template program from cache
            string bodyHash = Utils.ComputeHash(templateBody);
            Program program;
            lock (TemplateProgramCacheLock)
            {
                if (TemplateProgramCache.TryGetValue(bodyHash, out program))
                    return program;
            }

            // Per-template-body compiling state
            _programCommands = new List<ICommand>();
            _endTagsCommandMap = new Dictionary<int, int>();
            _macroMap = new Dictionary<string, IProgram>();
            _tagStack = new List<TagStackItem>();
            _endTagCommandLocationCounter = 0;
            _currentStartTag = null;

            // Parse template
            ParseTemplate(templateBody, templatePath, DefaultNamespaces);

            // Create template program instance
            program = new Program(templateBody, templatePath, bodyHash, _programCommands, _endTagsCommandMap, _macroMap, _importMacroCommands);

            // Put template program to cache
            lock (TemplateProgramCacheLock)
            {
                if (!TemplateProgramCache.ContainsKey(bodyHash))
                    TemplateProgramCache.Add(bodyHash, program);
            }

            return program;
        }
        void HandleElement(Element e)
        {
            if (e.Kind == ElementKind.Element || e.Kind == ElementKind.StartTag)
            {
                // Start tag
                var name = e.StartTagTokens["name"] as Token;
                var suffix = e.StartTagTokens["suffix"] as Token;
                Location loc = name.Location;
                var tag = new Tag
                {
                    Name = name.ToString(),
                    Suffix = suffix.ToString(),
                    SourcePath = name.Filename,
                    LineNumber = loc.Line,
                    LinePosition = loc.Position,
                    Attributes = new List<TagAttribute>()
                };
                var attrs = e.StartTagTokens["attrs"] as List<Dictionary<string, object>>;
                foreach (var attr in attrs)
                {
                    var attrName = attr["name"] as Token;
                    var attrValue = attr["value"] as Token;
                    var attrEq = attr["eq"] as Token;
                    var attrQuote = attr["quote"] as Token;
                    var a = new TagAttribute
                    {
                        Name = attrName.ToString(),
                        Value = attrValue.ToString(),
                        Eq = attrEq.ToString(),
                        Quote = attrQuote.ToString(),
                        QuoteEntity = Utils.Char2Entity(attrQuote.ToString())
                    };
                    tag.Attributes.Add(a);
                }
                if ((e.Children.Count == 0 && suffix.ToString() == "/>") || e.EndTagTokens.Count == 0)
                {
                    // Singleton element
                    tag.Singleton = true;
                    HandleStartTag(tag);
                    HandleEndTag(tag);
                }
                else
                {
                    tag.Singleton = false;
                    HandleStartTag(tag);
                }

                // Children
                foreach (var item in e.Children)
                    HandleElement(item);

                // End tag
                if (e.EndTagTokens.Count > 0)
                {
                    var endName = e.EndTagTokens["name"] as Token;
                    var endSuffix = e.EndTagTokens["suffix"] as Token;
                    Location endLoc = endName.Location;
                    var endTag = new Tag
                    {
                        Name = endName.ToString(),
                        Suffix = endSuffix.ToString(),
                        SourcePath = endName.Filename,
                        LineNumber = endLoc.Line,
                        LinePosition = endLoc.Position
                    };
                    HandleEndTag(endTag);
                }
            }
            else if (e.Kind == ElementKind.Text)
            {
                foreach (Token token in e.StartTagTokens.Values)
                    HandleData(token.ToString());
            }
            else if (e.Kind == ElementKind.Comment)
            {
                foreach (Token token in e.StartTagTokens.Values)
                    HandleComment(token.ToString());
            }
            else if (e.Kind == ElementKind.CData)
            {
                foreach (Token token in e.StartTagTokens.Values)
                    HandleCData(token.ToString());
            }
            else if (e.Kind == ElementKind.ProcessingInstruction)
            {
                HandleProcessingInstruction(e);
            }
            else if (e.Kind == ElementKind.Default)
            {
                foreach (Token token in e.StartTagTokens.Values)
                    HandleDefault(token.ToString());
            }
        }
Ejemplo n.º 24
0
 public Command(Tag tag, CommandType commandType)
 {
     if (tag != null)
         Tag = new Tag(tag);
     CommandType = commandType;
 }
Ejemplo n.º 25
0
 public CmdStartTag(Tag tag)
     : base(tag, CommandType.CmdStartTag)
 {
 }