Beispiel #1
1
func namespacedTree(tree *parse.Tree, ns []string) *parse.Tree {
	tree = tree.Copy()
	if len(ns) > 0 {
		prefix := strings.Join(ns, nsSep) + nsMark
		templateutil.WalkTree(tree, func(n, p parse.Node) {
			if n.Type() == parse.NodeTemplate {
				tmpl := n.(*parse.TemplateNode)
				tmpl.Name = prefix + tmpl.Name
			}
		})
	}
	return tree
}
Beispiel #2
0
func (s *State) formatTreeErr(name string, tr *parse.Tree, node parse.Node, err error) error {
	loc, _ := tr.ErrorContext(node)
	if loc != "" {
		// Might to adjust the column due to the prepend varNop nodes
		file, line, col, ok := splitErrorContext(loc)
		if ok {
			col -= s.p.tmpl.offsets[tr][line]
			loc = fmt.Sprintf("%s:%d:%d", file, line, col)
		}
		err = fmt.Errorf("%s: %s", loc, err.Error())
	}
	return err
}
Beispiel #3
0
func processPageTemplate(filename string, tree *parse.Tree) {
	// Prefix ~ template names with the file name.
	// ~ denotes a template used as a master page content section.
	// We prefix these with the file name to prevent 'redefinition of template'
	// errors when we store all of the templates from multiple files
	// in the same template set.
	if strings.HasPrefix(tree.Name, "~") {
		tree.Name = filename + tree.Name
	}
	if strings.HasPrefix(tree.ParseName, "~") {
		tree.ParseName = filename + tree.ParseName
	}
	fmt.Printf("\tdefine: %s\n", tree.Name)

	// Iterate the parse tree and update any
	// {{template "~..."}} nodes to use the file name prefix.
	prefixTildeTemplates(filename, tree.Root.Nodes)
}
Beispiel #4
0
// removeVarNopNodes removes any nodes of the form
// {{ $Something := _gondola_nop }}
// They are used to fool the parser and letting us parse
// variable nodes which haven't been previously defined
// in the same template.
func (t *Template) removeVarNopNodes(tr *parse.Tree, nodes []parse.Node) []parse.Node {
	var newNodes []parse.Node
	for _, v := range nodes {
		if an, ok := v.(*parse.ActionNode); ok {
			if len(an.Pipe.Cmds) == 1 && len(an.Pipe.Cmds[0].Args) == 1 {
				if id, ok := an.Pipe.Cmds[0].Args[0].(*parse.IdentifierNode); ok && id.Ident == varNop {
					// Store offset for errors
					loc, _ := tr.ErrorContext(v)
					if _, line, _, ok := splitErrorContext(loc); ok {
						if t.offsets[tr] == nil {
							t.offsets[tr] = make(map[int]int)
						}
						varName := an.Pipe.Decl[0].Ident[0]
						// delim (2) + space (1) + len(varname) + space(1) + := (2) + space(1) + len(varNop) + space (1) + delim (2)
						t.offsets[tr][line] += 2 + 1 + len(varName) + 1 + 2 + 1 + len(varNop) + 1 + 2
					}
					continue
				}
			}
		}
		newNodes = append(newNodes, v)
	}
	return newNodes
}
Beispiel #5
0
// ReplaceTranslatableBlocks replaces begintrans/endtrans blocks
// with an equivalent action using the translation function named
// by fn.
func ReplaceTranslatableBlocks(tr *parse.Tree, fn string) error {
	var err error
	WalkTree(tr, func(n, p parse.Node) {
		if err != nil {
			return
		}
		if IsPseudoFunction(n, BeginTranslatableBlock) {
			list, ok := p.(*parse.ListNode)
			if !ok {
				loc, ctx := tr.ErrorContext(n)
				err = fmt.Errorf("%s:%s:%s not in ListNode (%T)", loc, ctx, BeginTranslatableBlock, p)
				return
			}
			cmd := &parse.CommandNode{
				NodeType: parse.NodeCommand,
				Pos:      n.Position(),
			}
			pipe := &parse.PipeNode{
				NodeType: parse.NodePipe,
				Pos:      n.Position(),
				Cmds:     []*parse.CommandNode{cmd},
			}
			repl := &parse.ActionNode{
				NodeType: parse.NodeAction,
				Pos:      n.Position(),
				Pipe:     pipe,
			}
			if repl != nil {
			}
			pos := -1
			for ii, v := range list.Nodes {
				if v == n {
					pos = ii
					break
				}
			}
			var pipes []parse.Node
			var buf bytes.Buffer
			endPos := -1
		Nodes:
			for ii, v := range list.Nodes[pos+1:] {
				switch x := v.(type) {
				case *parse.TextNode:
					buf.Write(x.Text)
				case *parse.ActionNode:
					if IsPseudoFunction(x, EndTranslatableBlock) {
						endPos = ii
						break Nodes
					}
					if len(x.Pipe.Decl) > 0 {
						loc, ctx := tr.ErrorContext(n)
						err = fmt.Errorf("%s:%s:%s translatable block can't contain a pipe with declaractions", loc, ctx, v)
					}
					buf.WriteString("%v")
					pipes = append(pipes, x.Pipe)
				default:
					loc, ctx := tr.ErrorContext(n)
					err = fmt.Errorf("%s translatable block can't contain %T %s", loc, v, ctx)
					return
				}
			}
			if buf.Len() > 0 {
				text := buf.String()
				quoted := strconv.Quote(text)
				innerPipe := &parse.PipeNode{
					NodeType: parse.NodePipe,
					Pos:      n.Position(),
					Cmds: []*parse.CommandNode{
						&parse.CommandNode{
							NodeType: parse.NodeCommand,
							Pos:      n.Position(),
							Args: []parse.Node{parse.NewIdentifier(fn), &parse.StringNode{
								NodeType: parse.NodeString,
								Pos:      n.Position(),
								Quoted:   quoted,
								Text:     text,
							}},
						},
					},
				}
				cmd.Args = append(cmd.Args, parse.NewIdentifier("printf"), innerPipe)
				cmd.Args = append(cmd.Args, pipes...)
			}
			nodes := list.Nodes[:pos]
			nodes = append(nodes, repl)
			nodes = append(nodes, list.Nodes[endPos+pos+1:]...)
			list.Nodes = nodes
		}
	})
	return err
}