Add landing page for kjol, documentation
This commit is contained in:
99
go/webui/code_test.go
Normal file
99
go/webui/code_test.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package webui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The highlighter emits HTML, and its input is Go source — which is full of <, > and &.
|
||||
// Anything that reaches the page unescaped is markup injection into your own docs page:
|
||||
// a snippet containing `<div>` would render a div.
|
||||
func TestHighlightGoEscapes(t *testing.T) {
|
||||
got := HighlightGo(`s := "<div class=\"x\">" // a & b`)
|
||||
|
||||
if strings.Contains(got, "<div") {
|
||||
t.Errorf("a `<div>` in the SOURCE reached the output as markup:\n%s", got)
|
||||
}
|
||||
if !strings.Contains(got, "<div") {
|
||||
t.Errorf("the angle bracket was not escaped:\n%s", got)
|
||||
}
|
||||
if !strings.Contains(got, "&") {
|
||||
t.Errorf("the ampersand was not escaped:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHighlightGoClassifies(t *testing.T) {
|
||||
got := HighlightGo("func main() { x := 42 // note\n}")
|
||||
|
||||
for _, want := range []struct{ what, class, text string }{
|
||||
{"keyword", goKeywordClass, "func"},
|
||||
{"call", goFuncClass, "main"},
|
||||
{"number", goNumberClass, "42"},
|
||||
{"comment", goCommentClass, "// note"},
|
||||
} {
|
||||
if !strings.Contains(got, `<span class="`+want.class+`">`+want.text+`</span>`) {
|
||||
t.Errorf("%s %q was not highlighted:\n%s", want.what, want.text, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The //gowasm: directives are the most important line in half these snippets. They are
|
||||
// comments, and must survive as such.
|
||||
func TestHighlightGoKeepsDirectives(t *testing.T) {
|
||||
got := HighlightGo("//gowasm:page / static layout=public\nfunc HomePage() {}")
|
||||
if !strings.Contains(got, `<span class="`+goCommentClass+`">//gowasm:page / static layout=public</span>`) {
|
||||
t.Errorf("the directive was not kept whole as a comment:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
// A lexer that can hang or eat the rest of the file on malformed input would take the
|
||||
// whole page down with it. Unterminated literals stop; they do not run away.
|
||||
func TestHighlightGoSurvivesMalformedInput(t *testing.T) {
|
||||
for _, src := range []string{
|
||||
`x := "unterminated`,
|
||||
"y := `unterminated raw",
|
||||
"/* unterminated block",
|
||||
`z := '`,
|
||||
"",
|
||||
} {
|
||||
got := HighlightGo(src)
|
||||
// The text must all still be there — mangling is not an acceptable failure mode
|
||||
// either. Compare on the visible characters, ignoring the spans.
|
||||
if plain := stripTags(got); plain != src {
|
||||
t.Errorf("input %q came out as %q", src, plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing is dropped: every byte of the source is still on the page, in order.
|
||||
func TestHighlightGoIsLossless(t *testing.T) {
|
||||
src := "package app\n\nimport \"strings\"\n\nfunc f(n int) string {\n\treturn strings.Repeat(\"x\", n) // pad\n}\n"
|
||||
if plain := stripTags(HighlightGo(src)); plain != src {
|
||||
t.Errorf("the highlighter changed the source.\n got: %q\nwant: %q", plain, src)
|
||||
}
|
||||
}
|
||||
|
||||
// stripTags removes the spans and unescapes, recovering the original source.
|
||||
func stripTags(s string) string {
|
||||
var b strings.Builder
|
||||
for i := 0; i < len(s); {
|
||||
if s[i] == '<' {
|
||||
j := strings.IndexByte(s[i:], '>')
|
||||
if j < 0 {
|
||||
break
|
||||
}
|
||||
i += j + 1
|
||||
continue
|
||||
}
|
||||
b.WriteByte(s[i])
|
||||
i++
|
||||
}
|
||||
out := b.String()
|
||||
// Reverse html.EscapeString, innermost last.
|
||||
out = strings.ReplaceAll(out, "<", "<")
|
||||
out = strings.ReplaceAll(out, ">", ">")
|
||||
out = strings.ReplaceAll(out, """, `"`)
|
||||
out = strings.ReplaceAll(out, "'", "'")
|
||||
out = strings.ReplaceAll(out, "&", "&")
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user