ref: c9faa5d093ef6a890e00fb92880ab1a2edf9801c
parent: 45d380a2ac7ab73fb8bf38cf3f261189529dc926
author: Philip Silva <philip.silva@protonmail.com>
date: Wed Dec 16 14:46:24 EST 2020
Correctly handle noscript fallthrough
--- a/browser/browser.go
+++ b/browser/browser.go
@@ -49,6 +49,7 @@
var numElements int64
var log *logger.Logger
var scroller *duit.Scroll
+var display *draw.Display
func SetLogger(l *logger.Logger) {
log = l
@@ -122,8 +123,8 @@
src string
}
-func NewImage(display *draw.Display, n nodes.Node) duit.UI {
- img, err := newImage(display, n)
+func NewImage(n nodes.Node) duit.UI {
+ img, err := newImage(n)
if err != nil {
log.Errorf("could not load image: %v", err)
return &duit.Label{}
@@ -131,7 +132,11 @@
return img
}
-func newImage(display *draw.Display, n nodes.Node) (ui duit.UI, err error) {
+func newImage(n nodes.Node) (ui duit.UI, err error) {
+ if display == nil {
+ // probably called from a unit test
+ return nil, fmt.Errorf("display nil")
+ }
src := attr(*n.DomSubtree, "src")
if src == "" {
return nil, fmt.Errorf("no src in %+v", n.Attr)
@@ -604,11 +609,11 @@
}
}
-func RichInnerContentFrom(r int, b *Browser, display *draw.Display, n *nodes.Node) *Element {
+func RichInnerContentFrom(r int, b *Browser, n *nodes.Node) *Element {
childrenAsEls := make([]*Element, 0, 1)
for _, c := range n.Children {
- tmp := NodeToBox(r+1, b, display, c)
+ tmp := NodeToBox(r+1, b, c)
if tmp != nil {
numElements++
el := NewElement(tmp, c.Map.ApplyChildStyle(style.TextNode))
@@ -683,7 +688,7 @@
return
}
-func (t *Table) Element(r int, b *Browser, display *draw.Display, cs style.Map) *Element {
+func (t *Table) Element(r int, b *Browser, cs style.Map) *Element {
numRows := len(t.rows)
numCols := t.numColsMax()
useOneGrid := t.numColsMin() == t.numColsMax()
@@ -692,7 +697,7 @@
uis := make([]duit.UI, 0, numRows*numCols)
for _, row := range t.rows {
for _, td := range row.columns {
- uis = append(uis, NodeToBox(r+1, b, display, td))
+ uis = append(uis, NodeToBox(r+1, b, td))
}
}
@@ -722,7 +727,7 @@
for _, row := range t.rows {
rowEls := make([]*Element, 0, len(row.columns))
for _, col := range row.columns {
- ui := NodeToBox(r+1, b, display, col)
+ ui := NodeToBox(r+1, b, col)
if ui != nil {
el := NewElement(ui, col.Map)
rowEls = append(rowEls, el)
@@ -788,7 +793,7 @@
return body
}
-func NodeToBox(r int, b *Browser, display *draw.Display, n *nodes.Node) *Element {
+func NodeToBox(r int, b *Browser, n *nodes.Node) *Element {
if attr(*n.DomSubtree, "aria-hidden") == "true" || hasAttr(*n.DomSubtree, "hidden") {
return nil
}
@@ -800,11 +805,6 @@
switch n.Data() {
case "style", "script", "svg", "template":
return nil
- case "noscript":
- if *ExperimentalJsInsecure {
- return nil
- }
- fallthrough
case "input":
numElements++
t := attr(*n.DomSubtree, "type")
@@ -831,7 +831,12 @@
}
case "table":
numElements++
- return NewTable(n).Element(r+1, b, display, n.Map)
+ return NewTable(n).Element(r+1, b, n.Map)
+ case "noscript":
+ if *ExperimentalJsInsecure {
+ return nil
+ }
+ fallthrough
case "body", "p", "h1", "center", "nav", "article", "header", "div", "td":
var innerContent duit.UI
if nodes.IsPureTextContent(*n) {
@@ -844,7 +849,7 @@
Map: n.Map.ApplyChildStyle(style.TextNode),
}
} else {
- innerContent = RichInnerContentFrom(r+1, b, display, n)
+ innerContent = RichInnerContentFrom(r+1, b, n)
}
numElements++
@@ -855,7 +860,7 @@
case "img":
numElements++
return NewElement(
- NewImage(display, *n),
+ NewImage(*n),
n.Map,
)
case "pre":
@@ -879,7 +884,7 @@
Map: n.Map,
}
} else {
- innerContent = RichInnerContentFrom(r+1, b, display, n)
+ innerContent = RichInnerContentFrom(r+1, b, n)
}
numElements++
@@ -907,7 +912,7 @@
} else {
// TODO: make blue borders and different
// mouse cursor and actually clickable
- innerContent = RichInnerContentFrom(r+1, b, display, n)
+ innerContent = RichInnerContentFrom(r+1, b, n)
}
numElements++
if innerContent == nil {
@@ -926,7 +931,7 @@
// Internal node object
els := make([]*Element, 0, 10)
for _, c := range n.Children {
- el := NodeToBox(r+1, b, display, c)
+ el := NodeToBox(r+1, b, c)
if el != nil && !c.IsDisplayNone() {
els = append(els, el)
}
@@ -1152,6 +1157,7 @@
browser = b
style.SetFetcher(b)
dui = _dui
+ display = dui.Display
b.layoutWebsite()
@@ -1485,7 +1491,7 @@
log.Printf("Layout website...")
numElements = 0
scroller = duit.NewScroll(
- NodeToBox(0, b, b.dui.Display, nodes.NewNodeTree(body, style.Map{}, nodeMap, nil)),
+ NodeToBox(0, b, nodes.NewNodeTree(body, style.Map{}, nodeMap, nil)),
)
b.Website.UI = scroller
log.Printf("Layouting done (%v elements created)", numElements)
@@ -1492,7 +1498,7 @@
if numElements < 10 {
log.Errorf("Less than 10 elements layouted, seems css processing failed. Will layout without css")
scroller = duit.NewScroll(
- NodeToBox(0, b, b.dui.Display, nodes.NewNodeTree(body, style.Map{}, make(map[*html.Node]style.Map), nil)),
+ NodeToBox(0, b, nodes.NewNodeTree(body, style.Map{}, make(map[*html.Node]style.Map), nil)),
)
b.Website.UI = scroller
}
--- a/browser/browser_test.go
+++ b/browser/browser_test.go
@@ -1,12 +1,23 @@
package browser
import (
+ "github.com/mjl-/duit"
+ "golang.org/x/net/html"
+ "net/http"
"net/url"
"opossum/logger"
+ "opossum/nodes"
+ "opossum/style"
+ "strings"
"testing"
)
func init() {
+ quiet := false
+ logger.Quiet = &quiet
+ js := false
+ ExperimentalJsInsecure = &js
+ logger.Init()
SetLogger(&logger.Logger{})
}
@@ -46,3 +57,44 @@
func TestNilPanic(t *testing.T) {
//f, err := os.Open()
}
+
+func TestNodeToBoxNoscript(t *testing.T) {
+ htm := `
+ <body>
+ <noscript>
+ <a href="https://example.com">Link</a>
+ </noscript>
+ <a>Other</a>
+ <input value=123>
+ </body>
+ `
+ doc, err := html.ParseWithOptions(
+ strings.NewReader(string(htm)),
+ html.ParseOptionEnableScripting(false),
+ )
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ nodeMap := make(map[*html.Node]style.Map)
+ body := grepBody(doc)
+ b := &Browser{}
+ b.client = &http.Client{}
+ browser = b
+ u, err := url.Parse("https://example.com")
+ if err != nil {
+ log.Fatalf("parse: %v", err)
+ }
+ b.History.Push(u)
+ nt := nodes.NewNodeTree(body, style.Map{}, nodeMap, nil)
+ boxed := NodeToBox(0, b, nt)
+ numInputs := 0
+ TraverseTree(boxed, func(ui duit.UI) {
+ if _, ok := ui.(*duit.Field); ok {
+ numInputs++
+ }
+ })
+ if numInputs != 1 {
+ t.Fail()
+ }
+}
+