Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ require (
github.com/linkdata/jq v0.6.0
github.com/linkdata/secureheaders v1.5.0
github.com/linkdata/staticserve v1.1.8
golang.org/x/net v0.58.0
)

require github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,3 @@ github.com/linkdata/staticserve v1.1.8/go.mod h1:uOUrHkbNEkVXWvuw7gk0ydm39r9Y1Re
github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
6 changes: 3 additions & 3 deletions lib/htmlio/AI.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ already trusted must be escaped before conversion to `template.HTML`.
## Verification

Run `go test -race ./lib/htmlio` and `go test ./lib/htmlio` from the module root.
Keep table and fuzz coverage for escaping, CR/NUL behavior, DOM-parsed values,
void elements, textarea/pre leading newlines, positive/zero/invalid Jids, and
Writer-error propagation.
Keep table and fuzz coverage for escaping, CR/NUL behavior, modeled DOM
attribute values, void elements, textarea/pre leading newlines,
positive/zero/invalid Jids, and Writer-error propagation.
46 changes: 11 additions & 35 deletions lib/htmlio/writehtml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/linkdata/jaws/lib/htmlio"
"github.com/linkdata/jaws/lib/jid"
xhtml "golang.org/x/net/html"
)

func Test_WriteHTMLInner(t *testing.T) {
Expand Down Expand Up @@ -458,38 +457,9 @@ func normalizeCR(s string) string {
return strings.ReplaceAll(s, "\r", "\n")
}

func parsedAttr(t *testing.T, source, name string) string {
t.Helper()
doc, err := xhtml.Parse(strings.NewReader(source))
if err != nil {
t.Fatal(err)
}
var findAttr func(*xhtml.Node) (string, bool)
findAttr = func(node *xhtml.Node) (string, bool) {
if node.Type == xhtml.ElementNode {
for _, attr := range node.Attr {
if attr.Key == name {
return attr.Val, true
}
}
}
for child := node.FirstChild; child != nil; child = child.NextSibling {
if value, ok := findAttr(child); ok {
return value, true
}
}
return "", false
}
if value, ok := findAttr(doc); ok {
return value
}
t.Fatalf("attribute %q not found in parsed source %q", name, source)
return ""
}

// TestAttr_DOMValue verifies the DOM attribute value exposed by an HTML
// parser. Carriage returns round-trip, while U+0000 is deliberately
// canonicalized to the U+FFFD value required by HTML parsing.
// TestAttr_DOMValue models the attribute value exposed by an HTML parser.
// Carriage returns round-trip, while U+0000 is deliberately canonicalized to
// the U+FFFD value required by HTML parsing.
func TestAttr_DOMValue(t *testing.T) {
values := []string{
"", "plain", "a\rb", "a\r\nb", "\rlead", "trail\r", "x\ry\rz",
Expand All @@ -501,9 +471,15 @@ func TestAttr_DOMValue(t *testing.T) {
if strings.IndexByte(src, 0) >= 0 {
t.Fatalf("Attr(%q) = %q, contains raw NUL", value, src)
}
got := parsedAttr(t, "<div "+src+"></div>", "data-x")
const prefix = `data-x="`
if len(src) <= len(prefix) || !strings.HasPrefix(src, prefix) || !strings.HasSuffix(src, `"`) {
t.Fatalf("Attr(%q) = %q, want a quoted data-x attribute", value, src)
}
// Attr's fixed quoted shape is checked above; model browser input
// preprocessing before character-reference decoding for its value.
got := html.UnescapeString(normalizeCR(src[len(prefix) : len(src)-1]))
if want := strings.ReplaceAll(value, "\x00", "\uFFFD"); got != want {
t.Errorf("attribute value %q parsed as %q, want %q (source %q)", value, got, want, src)
t.Errorf("attribute value %q decoded as %q, want %q (source %q)", value, got, want, src)
}
}
}
Expand Down
Loading