// EncodeHeader encodes the names of the time series in a JavaScript array format. func (x *SeriesSweeper) EncodeHeader(w io.Writer) error { var bw *bufio.Writer = bufio.NewWriter(w) bw.WriteString("[\"Time\",") for i, series := range x.series { bw.WriteByte(byte('"')) template.JSEscape(bw, []byte(series)) bw.WriteByte(byte('"')) if i < len(x.series)-1 { bw.WriteByte(byte(',')) } } bw.WriteByte(byte(']')) return bw.Flush() }
// jsonLocaleMarshal encodes into a locale specific quoted string func jsonLocaleMarshal(c *Money) ([]byte, error) { if c == nil || c.Valid == false { return nullString, nil } var b bytes.Buffer b.WriteString(`"`) lb, err := c.Localize() if err != nil { if PkgLog.IsDebug() { PkgLog.Debug("money.jsonLocaleMarshal.Localize", "err", err, "currency", c, "bytes", lb) } return nil, errgo.Mask(err) } template.JSEscape(&b, lb) b.WriteString(`"`) return b.Bytes(), err }
// jsonExtendedMarshal encodes a currency into a JSON array: [1234.56, "€", "1.234,56 €"] func jsonExtendedMarshal(c *Money) ([]byte, error) { if c == nil || c.Valid == false { return nullString, nil } var b bytes.Buffer b.WriteRune('[') b.Write(c.Ftoa()) b.WriteString(`, "`) b.WriteString(template.JSEscapeString(string(c.Symbol()))) b.WriteString(`", "`) lb, err := c.Localize() if err != nil { if PkgLog.IsDebug() { PkgLog.Debug("money.jsonExtendedMarshal.Localize", "err", err, "currency", c, "bytes", lb) } return nil, errgo.Mask(err) } template.JSEscape(&b, lb) b.WriteRune('"') b.WriteRune(']') return b.Bytes(), err }
// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. func JSEscape(w io.Writer, b []byte) { template.JSEscape(w, b) }
// walk recursively goes through each node and translates the nodes to // javascript, writing the result to s.wr func (s *state) walk(node ast.Node) { s.at(node) switch node := node.(type) { case *ast.SoyFileNode: s.visitSoyFile(node) case *ast.NamespaceNode: s.visitNamespace(node) case *ast.SoyDocNode: return case *ast.TemplateNode: s.visitTemplate(node) case *ast.ListNode: s.visitChildren(node) // Output nodes ---------- case *ast.RawTextNode: s.writeRawText(node.Text) case *ast.PrintNode: s.visitPrint(node) case *ast.MsgNode: s.walk(node.Body) case *ast.CssNode: if node.Expr != nil { s.jsln(s.bufferName, " += ", node.Expr, " + '-';") } s.writeRawText([]byte(node.Suffix)) case *ast.DebuggerNode: s.jsln("debugger;") case *ast.LogNode: s.bufferName += "_" s.jsln("var ", s.bufferName, " = '';") s.walk(node.Body) s.jsln("console.log(", s.bufferName, ");") s.bufferName = s.bufferName[:len(s.bufferName)-1] // Control flow ---------- case *ast.IfNode: s.visitIf(node) case *ast.ForNode: s.visitFor(node) case *ast.SwitchNode: s.visitSwitch(node) case *ast.CallNode: s.visitCall(node) case *ast.LetValueNode: s.jsln("var ", s.scope.makevar(node.Name), " = ", node.Expr, ";") case *ast.LetContentNode: var oldBufferName = s.bufferName s.bufferName = s.scope.makevar(node.Name) s.jsln("var ", s.bufferName, " = '';") s.walk(node.Body) s.bufferName = oldBufferName // Values ---------- case *ast.NullNode: s.js("null") case *ast.StringNode: s.js("'") template.JSEscape(s.wr, []byte(node.Value)) s.js("'") case *ast.IntNode: s.js(node.String()) case *ast.FloatNode: s.js(node.String()) case *ast.BoolNode: s.js(node.String()) case *ast.GlobalNode: s.visitGlobal(node) case *ast.ListLiteralNode: s.js("[") for i, item := range node.Items { if i != 0 { s.js(",") } s.walk(item) } s.js("]") case *ast.MapLiteralNode: s.js("{") var first = true for k, v := range node.Items { if !first { s.js(",") } first = false s.js(k, ":") s.walk(v) } s.js("}") case *ast.FunctionNode: s.visitFunction(node) case *ast.DataRefNode: s.visitDataRef(node) // Arithmetic operators ---------- case *ast.NegateNode: s.js("(-", node.Arg, ")") case *ast.AddNode: s.op("+", node) case *ast.SubNode: s.op("-", node) case *ast.DivNode: s.op("/", node) case *ast.MulNode: s.op("*", node) case *ast.ModNode: s.op("%", node) // Arithmetic comparisons ---------- case *ast.EqNode: s.op("==", node) case *ast.NotEqNode: s.op("!=", node) case *ast.LtNode: s.op("<", node) case *ast.LteNode: s.op("<=", node) case *ast.GtNode: s.op(">", node) case *ast.GteNode: s.op(">=", node) // Boolean operators ---------- case *ast.NotNode: s.js("!(", node.Arg, ")") case *ast.AndNode: s.op("&&", node) case *ast.OrNode: s.op("||", node) case *ast.ElvisNode: // ?: is specified to check for null. s.js("(", node.Arg1, " != null ? ", node.Arg1, " : ", node.Arg2, ")") case *ast.TernNode: s.js("(", node.Arg1, "?", node.Arg2, ":", node.Arg3, ")") default: s.errorf("unknown node (%T): %v", node, node) } }
func (s *state) writeRawText(text []byte) { s.indent() s.js(s.bufferName, " += '") template.JSEscape(s.wr, text) s.js("';\n") }