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()
+ }
+}
+
--
⑨