+++ /dev/null
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package htmlwriter
-
-import (
- "os";
- "io";
- "fmt";
-)
-
-// Writer is a filter implementing the io.Write interface.
-// It provides facilities to generate HTML tags and does
-// HTML-escaping for text written through Write. Incoming
-// text is assumed to be UTF-8 encoded.
-
-export type Writer struct {
- // TODO should not export any of the fields
- writer io.Write;
-}
-
-
-func (b *Writer) Init(writer io.Write) *Writer {
- b.writer = writer;
- return b;
-}
-
-
-/* export */ func (p *Writer) Write(buf *[]byte) (written int, err *os.Error) {
- i0 := 0;
- for i := i0; i < len(buf); i++ {
- var s string;
- switch buf[i] {
- case '<': s = "<";
- case '&': s = "&";
- default: continue;
- }
- // write HTML escape instead of buf[i]
- w1, e1 := p.writer.Write(buf[i0 : i]);
- if e1 != nil {
- return i0 + w1, e1;
- }
- w2, e2 := io.WriteString(p.writer, s);
- if e2 != nil {
- return i0 + w1 /* not w2! */, e2;
- }
- i0 = i + 1;
- }
- written, err = p.writer.Write(buf[i0 : len(buf)]);
- return len(buf), err;
-}
-
-
-// ----------------------------------------------------------------------------
-// HTML-specific interface
-
-/* export */ func (p *Writer) Tag(s string) {
- // TODO proper error handling
- io.WriteString(p.writer, s);
-}
-
-
-// ----------------------------------------------------------------------------
-//
-
-export func New(writer io.Write) *Writer {
- return new(Writer).Init(writer);
-}
"tabwriter";
"flag";
"fmt";
- "htmlwriter";
Scanner "scanner";
AST "ast";
)
type Printer struct {
// output
text io.Write;
- tags *htmlwriter.Writer;
// comments
comments *array.Array; // the list of all comments
}
-func (P *Printer) Init(text io.Write, tags *htmlwriter.Writer, comments *array.Array) {
+func (P *Printer) Init(text io.Write, comments *array.Array) {
// writers
P.text = text;
- P.tags = tags;
// comments
P.comments = comments;
// ----------------------------------------------------------------------------
// Printing support
+func HtmlEscape(s string) string {
+ if html.BVal() {
+ var esc string;
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '<': esc = "<";
+ case '&': esc = "&";
+ default: continue;
+ }
+ return s[0 : i] + esc + HtmlEscape(s[i+1 : len(s)]);
+ }
+ }
+ return s;
+}
+
+
func (P *Printer) Printf(format string, s ...) {
n, err := fmt.fprintf(P.text, format, s);
if err != nil {
}
-func (P *Printer) String(pos int, s string) {
+func (P *Printer) TaggedString(pos int, tag, s, endtag string) {
// use estimate for pos if we don't have one
if pos == 0 {
pos = P.lastpos;
if debug.BVal() {
P.Printf("[%d]", P.cpos);
}
- P.Printf("%s", ctext);
+ P.Printf("%s", HtmlEscape(ctext));
if ctext[1] == '/' {
//-style comments must end in newline
if debug.BVal() {
P.Printf("[%d]", pos);
}
- P.Printf("%s", s);
+ P.Printf("%s%s%s", tag, HtmlEscape(s), endtag);
// --------------------------------
// interpret state
}
+func (P *Printer) String(pos int, s string) {
+ P.TaggedString(pos, "", s, "");
+}
+
+
func (P *Printer) Token(pos int, tok int) {
P.String(pos, Scanner.TokenString(tok));
}
// HTML support
func (P *Printer) HtmlPrologue(title string) {
- if P.tags != nil {
- P.tags.Tag(
+ if html.BVal() {
+ P.TaggedString(0,
"<html>\n"
"<head>\n"
" <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n"
- " <title>" + title + "</title>\n"
+ " <title>" + HtmlEscape(title) + "</title>\n"
" <style type=\"text/css\">\n"
" </style>\n"
"</head>\n"
"<body>\n"
- "<pre>\n"
+ "<pre>\n",
+ "", ""
)
}
}
func (P *Printer) HtmlEpilogue() {
- if P.tags != nil {
- P.tags.Tag(
+ if html.BVal() {
+ P.TaggedString(0,
"</pre>\n"
"</body>\n"
- "<html>\n"
+ "<html>\n",
+ "", ""
)
}
}
func (P *Printer) HtmlIdentifier(pos int, ident string) {
- if false && P.tags != nil {
- P.tags.Tag(`<a href="#` + ident + `">` + ident + `</a>`);
+ if html.BVal() {
+ // no need to HtmlEscape ident
+ P.TaggedString(pos, `<a href="#` + ident + `">`, ident, `</a>`);
} else {
P.String(pos, ident);
}
P.Stat(s.init);
P.separator = none;
}
- P.Printf(";");
+ P.String(0, ";");
P.separator = blank;
if s.expr != nil {
P.Expr(s.expr);
P.separator = none;
}
if s.tok == Scanner.FOR {
- P.Printf(";");
+ P.String(0, ";");
P.separator = blank;
if has_post {
P.Stat(s.post);
if usetabs.BVal() {
padchar = '\t';
}
- var (
- text = tabwriter.New(os.Stdout, int(tabwidth.IVal()), 1, padchar, true, html.BVal());
- tags *htmlwriter.Writer;
- )
- if html.BVal() {
- tags = htmlwriter.New(text);
- }
- P.Init(text, tags, prog.comments);
+ text := tabwriter.New(os.Stdout, int(tabwidth.IVal()), 1, padchar, true, html.BVal());
+ P.Init(text, prog.comments);
P.HtmlPrologue("<the source>");
P.Program(prog);