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 }
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 }
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) }
// 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 }
// 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 }