func formatCode(src []byte, annotations []doc.TypeAnnotation) string { // Collect comment positions in type annotation with Name = "" var ( comments []doc.TypeAnnotation s scanner.Scanner ) fset := token.NewFileSet() file := fset.AddFile("", fset.Base(), len(src)) s.Init(file, src, nil, scanner.ScanComments) commentLoop: for { pos, tok, lit := s.Scan() switch tok { case token.EOF: break commentLoop case token.COMMENT: p := file.Offset(pos) comments = append(comments, doc.TypeAnnotation{Pos: p, End: p + len(lit)}) } } // Merge type annotations and comments without modifying the caller's slice // of annoations. switch { case len(comments) == 0: // nothing to do case len(annotations) == 0: annotations = comments default: annotations = append(comments, annotations...) sort.Sort(sortByPos(annotations)) } var buf bytes.Buffer last := 0 for _, a := range annotations { template.HTMLEscape(&buf, src[last:a.Pos]) if a.Name != "" { p := a.ImportPath if p != "" { p = "/" + p } buf.WriteString(`<a href="`) buf.WriteString(urlFn(p)) buf.WriteByte('#') buf.WriteString(urlFn(a.Name)) buf.WriteString(`">`) template.HTMLEscape(&buf, src[a.Pos:a.End]) buf.WriteString(`</a>`) } else { buf.WriteString(`<span class="com">`) template.HTMLEscape(&buf, src[a.Pos:a.End]) buf.WriteString(`</span>`) } last = a.End } template.HTMLEscape(&buf, src[last:]) return buf.String() }
func selectionTag(w io.Writer, text []byte, selections int) { if selections < len(startTags) { if tag := startTags[selections]; len(tag) > 0 { w.Write(tag) template.HTMLEscape(w, text) w.Write(endTag) return } } template.HTMLEscape(w, text) }
func pathEscFmt(w io.Writer, format string, x ...interface{}) { switch v := x[0].(type) { case []byte: template.HTMLEscape(w, v) case string: template.HTMLEscape(w, []byte(filepath.ToSlash(v))) default: var buf bytes.Buffer fmt.Fprint(&buf, x) template.HTMLEscape(w, buf.Bytes()) } }
func htmlEscFmt(w io.Writer, format string, x ...interface{}) { switch v := x[0].(type) { case int: template.HTMLEscape(w, []byte(strconv.Itoa(v))) case []byte: template.HTMLEscape(w, v) case string: template.HTMLEscape(w, []byte(v)) default: var buf bytes.Buffer fmt.Fprint(&buf, x) template.HTMLEscape(w, buf.Bytes()) } }
func (p HTMLPrinter) Print(w io.Writer, kind syntaxhighlight.Kind, tokText string) error { class := HTMLConfig(p)[kind] if class != "" { _, err := w.Write([]byte(`<span class="`)) if err != nil { return err } _, err = io.WriteString(w, class) if err != nil { return err } io.WriteString(w, " input-block") // For "display: block;" style. _, err = w.Write([]byte(`">`)) if err != nil { return err } } template.HTMLEscape(w, []byte(tokText)) if class != "" { _, err := w.Write([]byte(`</span>`)) if err != nil { return err } } return nil }
func (p HTMLPrinter) Print(w io.Writer, kind Kind, tokText string) error { class := ((HTMLConfig)(p)).class(kind) if class != "" { _, err := w.Write([]byte(`<span class="`)) if err != nil { return err } _, err = io.WriteString(w, class) if err != nil { return err } _, err = w.Write([]byte(`">`)) if err != nil { return err } } template.HTMLEscape(w, []byte(tokText)) if class != "" { _, err := w.Write([]byte(`</span>`)) if err != nil { return err } } return nil }
func login(w http.ResponseWriter, r *http.Request) { fmt.Println("method:", r.Method) //获取请求的方法 if r.Method == "GET" { crutime := time.Now().Unix() h := md5.New() io.WriteString(h, strconv.FormatInt(crutime, 10)) token := fmt.Sprintf("%x", h.Sum(nil)) t, _ := template.ParseFiles("login.gtpl") t.Execute(w, token) } else { //请求的是登陆数据,那么执行登陆的逻辑判断 r.ParseForm() token := r.Form.Get("token") fmt.Println(token) if token != "" { fmt.Println("***************************") //验证token的合法性 } else { fmt.Println("============================") //不存在token报错 } fmt.Println("username length:", len(r.Form["username"][0])) fmt.Println("username:"******"username"))) //输出到服务器端 fmt.Println("password:"******"password"))) template.HTMLEscape(w, []byte(r.Form.Get("username"))) //输出到客户端 } }
func posLink_urlFunc(node ast.Node, fset *token.FileSet) string { var relpath string var line int var low, high int // selection if p := node.Pos(); p.IsValid() { pos := fset.Position(p) relpath = pos.Filename line = pos.Line low = pos.Offset } if p := node.End(); p.IsValid() { high = fset.Position(p).Offset } var buf bytes.Buffer template.HTMLEscape(&buf, []byte(relpath)) // selection ranges are of form "s=low:high" if low < high { fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping // if we have a selection, position the page // such that the selection is a bit below the top line -= 10 if line < 1 { line = 1 } } // line id's in html-printed source are of the // form "L%d" where %d stands for the line number if line > 0 { fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping } return buf.String() }
func login(w http.ResponseWriter, r *http.Request) { fmt.Println("method:", r.Method) //get request method if r.Method == "GET" { crutime := time.Now().Unix() h := md5.New() io.WriteString(h, strconv.FormatInt(crutime, 10)) token := fmt.Sprintf("%x", h.Sum(nil)) t, _ := template.ParseFiles("login.gtpl") t.Execute(w, token) } else { // log in request r.ParseForm() token := r.Form.Get("token") if token != "" { fmt.Println("Token: ", token) // check token validity } else { // give error if no token } fmt.Println("username length:", len(r.Form["username"][0])) fmt.Println("username:"******"username"))) // print in server side fmt.Println("password:"******"password"))) template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client } }
func prettySource(filename string, source string, limit int) (code string, err error) { prettyCode, ok := Print(filename, source) if ok != nil { // If it fails to parse, just serve it raw. coll := new(bytes.Buffer) template.HTMLEscape(coll, []byte(source)) prettyCode = coll.String() } linesPre := Pre().Attrs(As{"class": "line-numbers"}) codePre := Pre().Attrs(As{"class": "code-lines"}) stopped := false for i, code := range strings.SplitN(prettyCode, "\n", -1) { line := i + 1 linesPre.Append( fmt.Sprintf( A("%d").Attrs(As{ "rel": "#L%d", "href": "#LC%d", "id": "LID%d", }).Out()+"\n", line, line, line, line)) codePre.Append( Div(code).Attrs(As{ "class": "line", "id": "LC" + fmt.Sprint(line), }).Out()) if limit != 0 && i == limit { stopped = true break } } if stopped { linesPre.Append("\n") codePre.Append( Div( "\n", A("...").Attrs(As{ "href": fmt.Sprintf("/view/%s", filename), "class": "go-comment", })).Attrs(As{ "class": "line", }).Out()) } code = Table( Tbody( Tr( Td(linesPre).Attrs(As{"width": "1%", "valign": "top"}), Td(codePre).Attrs(As{"valign": "top"})))).Attrs(As{ "class": "code", "cellspacing": "0", "cellpadding": "0", }).Out() return }
// Emphasize and escape a line of text for HTML. URLs are converted into links; // if the URL also appears in the words map, the link is taken from the map (if // the corresponding map value is the empty string, the URL is not converted // into a link). Go identifiers that appear in the words map are italicized; if // the corresponding map value is not the empty string, it is considered a URL // and the word is converted into a link. If nice is set, the remaining text's // appearance is improved where it makes sense (e.g., `` is turned into “ // and '' into ”). func emphasize(w io.Writer, line string, words map[string]string, nice bool) { for { m := matchRx.FindStringSubmatchIndex(line) if m == nil { break } // m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx) // write text before match commentEscape(w, line[0:m[0]], nice) // adjust match if necessary match := line[m[0]:m[1]] if n := pairedParensPrefixLen(match); n < len(match) { // match contains unpaired parentheses (rare); // redo matching with shortened line for correct indices m = matchRx.FindStringSubmatchIndex(line[:m[0]+n]) match = match[:n] } // analyze match url := "" italics := false if words != nil { url, italics = words[match] } if m[2] >= 0 { // match against first parenthesized sub-regexp; must be match against urlRx if !italics { // no alternative URL in words list, use match instead url = match } italics = false // don't italicize URLs } // write match if len(url) > 0 { w.Write(html_a) template.HTMLEscape(w, []byte(url)) w.Write(html_aq) } if italics { w.Write(html_i) } commentEscape(w, match, nice) if italics { w.Write(html_endi) } if len(url) > 0 { w.Write(html_enda) } // advance line = line[m[1]:] } commentEscape(w, line, nice) }
// Escape comment text for HTML. If nice is set, // also turn `` into “ and '' into ”. func commentEscape(w io.Writer, text string, nice bool) { last := 0 if nice { for i := 0; i < len(text)-1; i++ { ch := text[i] if ch == text[i+1] && (ch == '`' || ch == '\'') { template.HTMLEscape(w, []byte(text[last:i])) last = i + 2 switch ch { case '`': w.Write(ldquo) case '\'': w.Write(rdquo) } i++ // loop will add one more } } } template.HTMLEscape(w, []byte(text[last:])) }
// codewalkFileprint serves requests with ?fileprint=f&lo=lo&hi=hi. // The filename f has already been retrieved and is passed as an argument. // Lo and hi are the numbers of the first and last line to highlight // in the response. This format is used for the middle window pane // of the codewalk pages. It is a separate iframe and does not get // the usual godoc HTML wrapper. func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) { abspath := f data, err := vfs.ReadFile(fs, abspath) if err != nil { log.Print(err) pres.ServeError(w, r, f, err) return } lo, _ := strconv.Atoi(r.FormValue("lo")) hi, _ := strconv.Atoi(r.FormValue("hi")) if hi < lo { hi = lo } lo = lineToByte(data, lo) hi = lineToByte(data, hi+1) // Put the mark 4 lines before lo, so that the iframe // shows a few lines of context before the highlighted // section. n := 4 mark := lo for ; mark > 0 && n > 0; mark-- { if data[mark-1] == '\n' { if n--; n == 0 { break } } } io.WriteString(w, `<style type="text/css">@import "/doc/codewalk/codewalk.css";</style><pre>`) template.HTMLEscape(w, data[0:mark]) io.WriteString(w, "<a name='mark'></a>") template.HTMLEscape(w, data[mark:lo]) if lo < hi { io.WriteString(w, "<div class='codewalkhighlight'>") template.HTMLEscape(w, data[lo:hi]) io.WriteString(w, "</div>") } template.HTMLEscape(w, data[hi:]) io.WriteString(w, "</pre>") }
func ExampleAnnotate() { src := []byte(`package main import "fmt" func main() { fmt.Println("Hey there, Go.") } `) // debugAnnotator implements syntaxhighlight.Annotator and prints the parameters it's given. p := debugAnnotator{Annotator: syntaxhighlight.HTMLAnnotator(syntaxhighlight.DefaultHTMLConfig)} anns, err := highlight_go.Annotate(src, p) if err != nil { log.Fatalln(err) } sort.Sort(anns) b, err := annotate.Annotate(src, anns, func(w io.Writer, b []byte) { template.HTMLEscape(w, b) }) if err != nil { log.Fatalln(err) } fmt.Println(string(b)) // Output: // Annotate(0, syntaxhighlight.Keyword, "package") // Annotate(8, syntaxhighlight.Plaintext, "main") // Annotate(14, syntaxhighlight.Keyword, "import") // Annotate(21, syntaxhighlight.String, "\"fmt\"") // Annotate(28, syntaxhighlight.Keyword, "func") // Annotate(33, syntaxhighlight.Plaintext, "main") // Annotate(37, syntaxhighlight.Plaintext, "(") // Annotate(38, syntaxhighlight.Plaintext, ")") // Annotate(40, syntaxhighlight.Plaintext, "{") // Annotate(43, syntaxhighlight.Plaintext, "fmt") // Annotate(46, syntaxhighlight.Plaintext, ".") // Annotate(47, syntaxhighlight.Plaintext, "Println") // Annotate(54, syntaxhighlight.Plaintext, "(") // Annotate(55, syntaxhighlight.String, "\"Hey there, Go.\"") // Annotate(71, syntaxhighlight.Plaintext, ")") // Annotate(73, syntaxhighlight.Plaintext, "}") // <span class="kwd">package</span> <span class="pln">main</span> // // <span class="kwd">import</span> <span class="str">"fmt"</span> // // <span class="kwd">func</span> <span class="pln">main</span><span class="pln">(</span><span class="pln">)</span> <span class="pln">{</span> // <span class="pln">fmt</span><span class="pln">.</span><span class="pln">Println</span><span class="pln">(</span><span class="str">"Hey there, Go."</span><span class="pln">)</span> // <span class="pln">}</span> }
// declFmt formats a Decl as HTML. func declFmt(decl doc.Decl) string { var buf bytes.Buffer last := 0 t := []byte(decl.Text) for _, a := range decl.Annotations { p := a.ImportPath if p != "" { p = "/" + p } template.HTMLEscape(&buf, t[last:a.Pos]) //buf.WriteString(`<a href="`) //buf.WriteString(urlFmt(p)) //buf.WriteByte('#') //buf.WriteString(urlFmt(a.Name)) //buf.WriteString(`">`) template.HTMLEscape(&buf, t[a.Pos:a.End]) //buf.WriteString(`</a>`) last = a.End } template.HTMLEscape(&buf, t[last:]) return buf.String() }
func main() { // handle input flag.Parse() if *srcFn == "" || *getName == "" { flag.Usage() os.Exit(2) } // load file fs := token.NewFileSet() file, err := parser.ParseFile(fs, *srcFn, nil, 0) if err != nil { log.Fatal(err) } // create filter filter := func(name string) bool { return name == *getName } // filter if !ast.FilterFile(file, filter) { os.Exit(1) } // print the AST var b bytes.Buffer printer.Fprint(&b, fs, file) // drop package declaration if !*showPkg { for { c, err := b.ReadByte() if c == '\n' || err != nil { break } } } // drop leading newlines for { b, err := b.ReadByte() if err != nil { break } if b != '\n' { os.Stdout.Write([]byte{b}) break } } // output if *html { template.HTMLEscape(os.Stdout, b.Bytes()) } else { b.WriteTo(os.Stdout) } }
// Emphasize and escape a line of text for HTML. URLs are converted into links; // if the URL also appears in the words map, the link is taken from the map (if // the corresponding map value is the empty string, the URL is not converted // into a link). Go identifiers that appear in the words map are italicized; if // the corresponding map value is not the empty string, it is considered a URL // and the word is converted into a link. If nice is set, the remaining text's // appearance is improved where it makes sense (e.g., `` is turned into “ // and '' into ”). func emphasize(w io.Writer, line string, words map[string]string, nice bool) { for { m := matchRx.FindStringSubmatchIndex(line) if m == nil { break } // m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx) // write text before match commentEscape(w, line[0:m[0]], nice) // analyze match match := line[m[0]:m[1]] url := "" italics := false if words != nil { url, italics = words[string(match)] } if m[2] >= 0 { // match against first parenthesized sub-regexp; must be match against urlRx if !italics { // no alternative URL in words list, use match instead url = string(match) } italics = false // don't italicize URLs } // write match if len(url) > 0 { w.Write(html_a) template.HTMLEscape(w, []byte(url)) w.Write(html_aq) } if italics { w.Write(html_i) } commentEscape(w, match, nice) if italics { w.Write(html_endi) } if len(url) > 0 { w.Write(html_enda) } // advance line = line[m[1]:] } commentEscape(w, line, nice) }
func breadcrumbsFmt(pdoc *doc.Package) string { importPath := []byte(pdoc.ImportPath) var buf bytes.Buffer i := 0 j := len(pdoc.ProjectRoot) switch { case j == 0: buf.WriteString("<a href=\"/-/go\" title=\"Standard Packages\">☆</a> ") j = bytes.IndexByte(importPath, '/') case j >= len(importPath): j = -1 } for j > 0 { buf.WriteString(`<a href="/`) buf.WriteString(urlFmt(string(importPath[:i+j]))) buf.WriteString(`">`) template.HTMLEscape(&buf, importPath[i:i+j]) buf.WriteString(`</a>/`) i = i + j + 1 j = bytes.IndexByte(importPath[i:], '/') } template.HTMLEscape(&buf, importPath[i:]) return buf.String() }
// n must be an ast.Node or a *doc.Note func posLink_urlFunc(info *PageInfo, n interface{}) string { var pos, end token.Pos switch n := n.(type) { case ast.Node: pos = n.Pos() end = n.End() case *doc.Note: pos = n.Pos end = n.End default: panic(fmt.Sprintf("wrong type for posLink_url template formatter: %T", n)) } var relpath string var line int var low, high int // selection offset range if pos.IsValid() { p := info.FSet.Position(pos) relpath = p.Filename line = p.Line low = p.Offset } if end.IsValid() { high = info.FSet.Position(end).Offset } var buf bytes.Buffer template.HTMLEscape(&buf, []byte(relpath)) // selection ranges are of form "s=low:high" if low < high { fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping // if we have a selection, position the page // such that the selection is a bit below the top line -= 10 if line < 1 { line = 1 } } // line id's in html-printed source are of the // form "L%d" where %d stands for the line number if line > 0 { fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping } return buf.String() }
func (s *state) evalPrint(node *ast.PrintNode) { s.walk(node.Arg) if _, ok := s.val.(data.Undefined); ok { s.errorf("In 'print' tag, expression %q evaluates to undefined.", node.Arg.String()) } var escapeHtml = s.autoescape != ast.AutoescapeOff var result = s.val for _, directiveNode := range node.Directives { var directive, ok = PrintDirectives[directiveNode.Name] if !ok { s.errorf("Print directive %q does not exist", directiveNode.Name) } if !checkNumArgs(directive.ValidArgLengths, len(directiveNode.Args)) { s.errorf("Print directive %q called with %v args, expected one of: %v", directiveNode.Name, len(directiveNode.Args), directive.ValidArgLengths) } var args []data.Value for _, arg := range directiveNode.Args { args = append(args, s.eval(arg)) } defer func() { if err := recover(); err != nil { s.errorf("panic in %v: %v\nexecuted: %v(%q, %v)\n%v", directiveNode, err, directiveNode.Name, result, args, string(debug.Stack())) } }() result = directive.Apply(result, args) if directive.CancelAutoescape { escapeHtml = false } } if escapeHtml { template.HTMLEscape(s.wr, []byte(result.String())) } else { if _, err := s.wr.Write([]byte(result.String())); err != nil { s.errorf("%s", err) } } }
func (t *TReplaser) replace(tpl parser.Ttpl, v map[string]interface{}, writer io.Writer) { for i := range tpl { switch tag := tpl[i].(type) { case tTagi18nCon: writer.Write(t.i18n.P(tag[0], v[tag[1]].([]interface{})...)) case tTagi18nVar: writer.Write(t.i18n.P(v[tag[0]].(string), v[tag[1]].([]interface{})...)) case tTagText: writer.Write(tag) case tTagVar: fmt.Fprint(writer, v[string(tag)]) case tTagVarHtmlEsc: template.HTMLEscape(writer, []byte(fmt.Sprint(v[string(tag)]))) case *tTagIncludeCon: t.replace(tag.tpl, getVarfromContext(tag.contextVar, v).(map[string]interface{}), writer) case tTagIncludeVar: t.Replace(tag[0], getVarfromContext(tag[1], v).(map[string]interface{}), writer) } } }
func srcPosLinkFunc(s string, line, low, high int) string { var buf bytes.Buffer template.HTMLEscape(&buf, []byte(s)) // selection ranges are of form "s=low:high" if low < high { fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping // if we have a selection, position the page // such that the selection is a bit below the top line -= 10 if line < 1 { line = 1 } } // line id's in html-printed source are of the // form "L%d" where %d stands for the line number if line > 0 { fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping } return buf.String() }
// FormatText HTML-escapes text and writes it to w. // Consecutive text segments are wrapped in HTML spans (with tags as // defined by startTags and endTag) as follows: // // - if line >= 0, line number (ln) spans are inserted before each line, // starting with the value of line // - if the text is Go source, comments get the "comment" span class // - each occurrence of the regular expression pattern gets the "highlight" // span class // - text segments covered by selection get the "selection" span class // // Comments, highlights, and selections may overlap arbitrarily; the respective // HTML span classes are specified in the startTags variable. // func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) { var comments, highlights Selection if goSource { comments = tokenSelection(text, token.COMMENT) } if pattern != "" { highlights = regexpSelection(text, pattern) } if line >= 0 || comments != nil || highlights != nil || selection != nil { var lineTag LinkWriter if line >= 0 { lineTag = func(w io.Writer, _ int, start bool) { if start { fmt.Fprintf(w, "<a id=\"L%d\"></a><span class=\"ln\">%6d</span>\t", line, line) line++ } } } FormatSelections(w, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection) } else { template.HTMLEscape(w, text) } }
func NextBus(w io.Writer, c appengine.Context) { item, err := memcache.Get(c, "nextbus") if err != nil { c.Errorf("%s", err) return } data := struct { Predictions []struct { RouteTag string `xml:"routeTag,attr"` Direction []struct { Title string `xml:"title,attr"` Prediction []prediction `xml:"prediction"` } `xml:"direction"` Message []struct { Text string `xml:"text,attr"` } `xml:"message"` } `xml:"predictions"` }{} if err := xml.Unmarshal(item.Value, &data); err != nil { c.Errorf("%s", err) return } // Messages are given per route, but they seem to be used for // systemwide messages. Annoyingly, not every route gets the // message, so we can't infer that a message is about a // systemwide event. seen := make(map[string]bool) for _, p := range data.Predictions { for _, m := range p.Message { if BoringMuniMessages[m.Text] || seen[m.Text] { continue } seen[m.Text] = true io.WriteString(w, `<div class=munimessage>`) template.HTMLEscape(w, []byte(m.Text)) io.WriteString(w, `</div>`) } } for _, p := range data.Predictions { for _, d := range p.Direction { io.WriteString(w, `<div class=bus><div class=route>`) template.HTMLEscape(w, []byte(p.RouteTag)) io.WriteString(w, ` <span class=smaller>`) title := d.Title title = strings.Replace(title, "Inbound", "inbound", -1) title = strings.Replace(title, "Outbound", "outbound", -1) title = strings.Replace(title, "Downtown", "downtown", -1) title = strings.Replace(title, " District", "", -1) title = strings.Replace(title, " Disrict", "", -1) template.HTMLEscape(w, []byte(title)) io.WriteString(w, `</span></div><div>`) for i, pp := range d.Prediction { if pp.Departure && i == 0 { io.WriteString(w, "departs ") } s := pp.String() io.WriteString(w, s) if i == len(d.Prediction)-1 { if s == "1" { io.WriteString(w, ` minute`) } else { io.WriteString(w, ` minutes`) } } else { io.WriteString(w, `, `) } } io.WriteString(w, `</div>`) } } }
func TestWithHTML(t *testing.T) { annsByFile := map[string][]*Annotation{ "hello_world.txt": []*Annotation{ {0, 5, []byte("<b>"), []byte("</b>"), 0}, {7, 12, []byte("<i>"), []byte("</i>"), 0}, }, "adjacent.txt": []*Annotation{ {0, 3, []byte("<b>"), []byte("</b>"), 0}, {3, 6, []byte("<i>"), []byte("</i>"), 0}, }, "empties.txt": []*Annotation{ {0, 0, []byte("<b>"), []byte("</b>"), 0}, {0, 0, []byte("<i>"), []byte("</i>"), 0}, {2, 2, []byte("<i>"), []byte("</i>"), 0}, }, "nested_0.txt": []*Annotation{ {0, 4, []byte("<1>"), []byte("</1>"), 0}, {1, 3, []byte("<2>"), []byte("</2>"), 0}, }, "nested_1.txt": []*Annotation{ {0, 4, []byte("<1>"), []byte("</1>"), 0}, {1, 3, []byte("<2>"), []byte("</2>"), 0}, {2, 2, []byte("<3>"), []byte("</3>"), 0}, }, "nested_2.txt": []*Annotation{ {0, 2, []byte("<1>"), []byte("</1>"), 0}, {2, 4, []byte("<2>"), []byte("</2>"), 0}, {4, 6, []byte("<3>"), []byte("</3>"), 0}, {7, 8, []byte("<4>"), []byte("</4>"), 0}, }, "html.txt": []*Annotation{ {193, 203, []byte("<1>"), []byte("</1>"), 0}, {336, 339, []byte("<WOOF>"), []byte("</WOOF>"), 0}, }, } dir := "testdata" tests, err := ioutil.ReadDir(dir) if err != nil { t.Fatal(err) } for _, test := range tests { name := test.Name() if !strings.Contains(name, *match) { continue } if strings.HasSuffix(name, ".html") { continue } path := filepath.Join(dir, name) input, err := ioutil.ReadFile(path) if err != nil { t.Fatal(err) continue } anns := annsByFile[name] var buf bytes.Buffer err = WithHTML(input, anns, func(w io.Writer, b []byte) { template.HTMLEscape(w, b) }, &buf) if err != nil { t.Errorf("%s: WithHTML: %s", name, err) continue } got := buf.Bytes() expPath := path + ".html" if *saveExp { err = ioutil.WriteFile(expPath, got, 0700) if err != nil { t.Fatal(err) } continue } want, err := ioutil.ReadFile(expPath) if err != nil { t.Fatal(err) } want = bytes.TrimSpace(want) got = bytes.TrimSpace(got) if !bytes.Equal(want, got) { t.Errorf("%s: want %q, got %q", name, want, got) continue } } if *saveExp { t.Fatal("overwrote all expected output files with actual output (run tests again without -exp)") } }
func main() { b, _ := ioutil.ReadAll(os.Stdin) template.HTMLEscape(os.Stdout, b) }
func Forecast(w io.Writer, c appengine.Context) { item, err := memcache.Get(c, "forecast") if err != nil { c.Errorf("%s", err) return } data := struct { Data []struct { Type string `xml:"type,attr"` TimeLayout []struct { LayoutKey string `xml:"layout-key"` StartValidTime []struct { PeriodName string `xml:"period-name,attr"` } `xml:"start-valid-time"` } `xml:"time-layout"` Parameters struct { WordedForecast struct { TimeLayout string `xml:"time-layout,attr"` Text []string `xml:"text"` } `xml:"wordedForecast"` } `xml:"parameters"` } `xml:"data"` }{} p := xml.NewDecoder(strings.NewReader(string(item.Value))) // NWS serves XML in ISO-8859-1 for no reason; the data is really ASCII. p.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) { return input, nil } if err = p.DecodeElement(&data, nil); err != nil { c.Errorf("%s", err) return } io.WriteString(w, `<div class=smaller style="text-align: left">`) for _, d := range data.Data { if d.Type != "forecast" { continue } var periods []string for _, tl := range d.TimeLayout { if tl.LayoutKey != d.Parameters.WordedForecast.TimeLayout { continue } for _, svt := range tl.StartValidTime { pn := svt.PeriodName pn = strings.Replace(pn, " Morning", " morning", -1) pn = strings.Replace(pn, " Afternoon", " afternoon", -1) pn = strings.Replace(pn, " Night", " night", -1) periods = append(periods, pn) } } texts := d.Parameters.WordedForecast.Text if len(texts) != len(periods) { c.Errorf("weather: len(texts) = %d, len(periods) = %d", len(texts), len(periods)) continue } if len(texts) > 4 { texts = texts[:4] } for i, text := range texts { io.WriteString(w, `<div style="margin-bottom: 8px"><span class=header>`) template.HTMLEscape(w, []byte(periods[i])) io.WriteString(w, `:</span> `) text = strings.Replace(text, "km/h", "km/\u2060h", -1) spaceSubs := make(map[int]string) matches := nbspRegexp.FindAllStringIndex(text, -1) if len(matches) > 0 { for i := 0; i < len(matches[0]); i += 2 { spaceSubs[matches[0][i]] = " " } } matches = thinspRegexp.FindAllStringIndex(text, -1) if len(matches) > 0 { for i := 0; i < len(matches[0]); i += 2 { spaceSubs[matches[0][i]+1] = `<span style="white-space: nowrap"> </span>` } } for i, ch := range text { sub, ok := spaceSubs[i] if ok { io.WriteString(w, sub) } else { io.WriteString(w, string(ch)) } } io.WriteString(w, `</div>`) } } io.WriteString(w, `</div>`) }
func textFmt(w io.Writer, format string, x ...interface{}) { var buf bytes.Buffer fmt.Fprint(&buf, x) template.HTMLEscape(w, buf.Bytes()) }
// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. func HTMLEscape(w io.Writer, b []byte) { template.HTMLEscape(w, b) }
// Template formatter for "time" format. func timeFmt(w io.Writer, format string, x ...interface{}) { template.HTMLEscape(w, []byte(time.Unix(x[0].(int64)/1e9, 0).String())) }