code: func (s *state) visitPrint(node *ast.PrintNode) {
  	var escape = s.autoescape
  	var directives []*ast.PrintDirectiveNode
  	for _, dir := range node.Directives {
  		var directive, ok = PrintDirectives[dir.Name]
  		if !ok {
  			s.errorf("Print directive %q not found", dir.Name)
  		}
  		if directive.CancelAutoescape {
  			escape = ast.AutoescapeOff
  		}
  		switch dir.Name {
  		case "id", "noAutoescape":
  			// no implementation, they just serve as a marker to cancel autoescape.
  		default:
  			directives = append(directives, dir)
  			if impt := s.options.Formatter.Directive(directive); impt != "" {
  				s.funcsCalled[dir.Name] = impt
  			}
  		}
  	}
  	if escape != ast.AutoescapeOff {
  		directives = append([]*ast.PrintDirectiveNode{{0, "escapeHtml", nil}}, directives...)
  	}
  
  	s.indent()
  	s.js(s.bufferName, " += ")
  	for _, dir := range directives {
  		s.js(PrintDirectives[dir.Name].Name, "(")
  	}
  	s.walk(node.Arg)
  	for i := range directives {
  		var dir = directives[len(directives)-1-i]
  		for _, arg := range dir.Args {
  			s.js(",")
  			s.walk(arg)
  		}
  		// soy specifies truncate adds ellipsis by default, so we have to pass
  		// doAddEllipsis = true to soy.$$truncate
  		if dir.Name == "truncate" && len(dir.Args) == 1 {
  			s.js(",true")
  		}
  		s.js(")")
  	}
  	s.js(";\n")
  }
docs: // TODO: unify print directives