shithub: mycel

Download patch

ref: 89d4bc312ff9a8639a4bf912f36e1a48e8a4e113
parent: df986b4853ae85c9e12bb773a6293bfcf23a8ea2
author: Philip Silva <philip.silva@protonmail.com>
date: Sun Oct 10 07:13:41 EDT 2021

add dom tree as fs

--- a/browser/browser.go
+++ b/browser/browser.go
@@ -220,7 +220,7 @@
 	}
 
 	if src == "" {
-		return nil, fmt.Errorf("no src in %+v", n.Attrs)
+		return nil, fmt.Errorf("no src in %+v", n.DomSubtree.Attr)
 	}
 
 	if i, cached = imageCache[src]; !cached {
--- a/browser/experimental_test.go
+++ b/browser/experimental_test.go
@@ -44,7 +44,7 @@
 		`$('body').hide()`,
 		`throw 'fail';`,
 	}
-	fs.DOM = nt
+	fs.SetDOM(nt)
 	fs.Update(h, nil, scripts)
 	js.NewJS(h, nil, nt)
 	js.Start()
--- /dev/null
+++ b/browser/fs/experimental.go
@@ -1,0 +1,146 @@
+package fs
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/knusbaum/go9p/fs"
+	"github.com/knusbaum/go9p/proto"
+	"github.com/psilva261/opossum/logger"
+	"github.com/psilva261/opossum/nodes"
+	"golang.org/x/net/html"
+)
+
+// Node such that one obtains a file structure like
+//
+// /0
+// /0/attrs
+// /0/html
+// /0/tag
+// /0/0
+//   ...
+// /0/1
+//   ...
+// ...
+//
+// (dir structure stolen from domfs)
+type Node struct {
+	name string
+	nt *nodes.Node
+}
+
+func (n Node) Stat() (s proto.Stat) {
+	s = *oFS.NewStat(n.name, un, gn, 0700)
+	s.Mode |= proto.DMDIR
+	// qtype bits should be consistent with Stat mode.
+	s.Qid.Qtype = uint8(s.Mode >> 24)
+	return
+}
+
+func (n Node) WriteStat(s *proto.Stat) error {
+	return nil
+}
+
+func (n Node) SetParent(p fs.Dir) {
+}
+
+func (n Node) Parent() fs.Dir {
+	return nil
+}
+
+func (n Node) Children() (cs map[string]fs.FSNode) {
+	cs = make(map[string]fs.FSNode)
+	if n.nt == nil {
+		return
+	}
+	for i, c := range n.nt.Children {
+		ddn := fmt.Sprintf("%v", i)
+		cs[ddn] = &Node{
+			name: ddn,
+			nt: c,
+		}
+	}
+	if n.nt.Type() == html.ElementNode {
+		cs["tag"] = n.tag()
+		cs["attrs"] = Attrs{attrs: &n.nt.DomSubtree.Attr}
+		cs["html"] = n.html()
+	}
+
+	return
+}
+
+func (n Node) tag() fs.FSNode {
+	return fs.NewDynamicFile(
+		oFS.NewStat("tag", un, gn, 0666),
+		func() []byte {
+			return []byte(n.nt.Data())
+		},
+	)
+}
+
+func (n Node) html() fs.FSNode {
+	return fs.NewDynamicFile(
+		oFS.NewStat("html", un, gn, 0666),
+		func() []byte {
+			buf := bytes.NewBufferString("")
+			if err := html.Render(buf, n.nt.DomSubtree); err != nil {
+				log.Errorf("render: %v", err)
+				return []byte{}
+			}
+			return []byte(buf.String())
+		},
+	)
+}
+
+func (n Node) AddChild(fs.FSNode) error {
+	return nil
+}
+
+func (n Node) DeleteChild(name string) error {
+	return fmt.Errorf("no removal possible")
+}
+
+type Attrs struct {
+	attrs *[]html.Attribute
+}
+
+func (as Attrs) Stat() (s proto.Stat) {
+	s = *oFS.NewStat("attrs", un, gn, 0500)
+	s.Mode |= proto.DMDIR
+	// qtype bits should be consistent with Stat mode.
+	s.Qid.Qtype = uint8(s.Mode >> 24)
+	return
+}
+
+func (as Attrs) WriteStat(s *proto.Stat) error {
+	return nil
+}
+
+func (as Attrs) SetParent(p fs.Dir) {
+}
+
+func (as Attrs) Parent() fs.Dir {
+	return nil
+}
+
+func (as Attrs) Children() (cs map[string]fs.FSNode) {
+	log.Infof("Attrs#Children()")
+	cs = make(map[string]fs.FSNode)
+	ff := func(k string) fs.FSNode {
+		return fs.NewDynamicFile(
+			oFS.NewStat(k, un, gn, 0666),
+			func() []byte {
+				var v string
+				for _, a := range *as.attrs {
+					if a.Key == k {
+						v = a.Val
+					}
+				}
+				return []byte(v)
+			},
+		)
+	}
+	for _, attr := range *as.attrs {
+		cs[attr.Key] = ff(attr.Key)
+	}
+	return 
+}
--- a/browser/fs/fs.go
+++ b/browser/fs/fs.go
@@ -25,21 +25,27 @@
 	gn      string
 	cssDir  *fs.StaticDir
 	jsDir   *fs.StaticDir
-	html    string
-	DOM     Queryable
+	htm     string
+	rt      *Node
 	Client  *http.Client
 	Fetcher opossum.Fetcher
 )
 
-type Queryable interface {
-	Query(q string) ([]*nodes.Node, error)
-}
-
 func init() {
 	mu = &sync.RWMutex{}
 	c = sync.NewCond(mu)
+	SetDOM(nil)
 }
 
+func SetDOM(d *nodes.Node) {
+	if rt == nil {
+		rt = &Node{
+			name: "0",
+		}
+	}
+	rt.nt = d
+}
+
 func Srv9p() {
 	c.L.Lock()
 	var root *fs.StaticDir
@@ -64,7 +70,7 @@
 			mu.RLock()
 			defer mu.RUnlock()
 
-			return []byte(html)
+			return []byte(htm)
 		},
 	)
 	root.AddChild(h)
@@ -87,6 +93,7 @@
 	q := fs.NewListenFile(oFS.NewStat("query", un, gn, 0600))
 	root.AddChild(q)
 	lq := (*fs.ListenFileListener)(q)
+	root.AddChild(rt)
 	go Query(lq)
 	if Client != nil {
 		xhr := fs.NewListenFile(oFS.NewStat("xhr", un, gn, 0600))
@@ -125,11 +132,11 @@
 	}
 	l = strings.TrimSpace(l)
 
-	if DOM == nil {
+	if rt.nt == nil {
 		log.Infof("DOM is nil")
 		return
 	}
-	nodes, err := DOM.Query(l)
+	nodes, err := rt.nt.Query(l)
 	if err != nil {
 		log.Errorf("query nodes: %v", err)
 		return
@@ -190,7 +197,7 @@
 	}
 }
 
-func Update(htm string, css []string, js []string) {
+func Update(html string, css []string, js []string) {
 	c.L.Lock()
 	defer c.L.Unlock()
 
@@ -198,7 +205,7 @@
 		c.Wait()
 	}
 
-	html = htm
+	htm = html
 	if cssDir != nil {
 		for name := range cssDir.Children() {
 			cssDir.DeleteChild(name)
--- a/browser/website.go
+++ b/browser/website.go
@@ -99,7 +99,7 @@
 		}
 		scripts = js.Scripts(nt, downloads)
 		fs.Update(htm, csss, scripts)
-		fs.DOM = nt
+		fs.SetDOM(nt)
 		log.Infof("JS pipeline start")
 		js.Stop()
 		jsProcessed, changed, err := processJS2()
@@ -152,7 +152,7 @@
 	}
 
 	fs.Update(htm, csss, scripts)
-	fs.DOM = nt
+	fs.SetDOM(nt)
 
 	log.Flush()
 }
--- a/js/js.go
+++ b/js/js.go
@@ -193,7 +193,7 @@
 			isJS := true
 			src := ""
 
-			for _, a := range n.Attrs {
+			for _, a := range n.DomSubtree.Attr {
 				switch strings.ToLower(a.Key) {
 				case "type":
 					t, err := opossum.NewContentType(a.Val, nil)
--- a/js/js_test.go
+++ b/js/js_test.go
@@ -41,7 +41,7 @@
 		t.Fatalf(err.Error())
 	}
 	nt := nodes.NewNodeTree(doc, style.Map{}, make(map[*html.Node]style.Map), nil)
-	fs.DOM = nt
+	fs.SetDOM(nt)
 	fs.Update(simpleHTML, nil, []string{string(buf), script})
 
 	NewJS(simpleHTML, nil, nil)
--- a/nodes/nodes.go
+++ b/nodes/nodes.go
@@ -14,7 +14,6 @@
 	DomSubtree *html.Node `json:"-"`
 	Text       string
 	Wrappable  bool
-	Attrs      []html.Attribute
 	style.Map
 	Children []*Node
 	parent   *Node `json:"-"`
@@ -46,7 +45,6 @@
 	}
 	n = &Node{
 		DomSubtree: doc,
-		Attrs:      doc.Attr,
 		Map:        ncs,
 		Children:   make([]*Node, 0, 2),
 		parent:     parent,
@@ -147,7 +145,7 @@
 }
 
 func (n *Node) Attr(k string) string {
-	for _, a := range n.Attrs {
+	for _, a := range n.DomSubtree.Attr {
 		if a.Key == k {
 			return a.Val
 		}
@@ -156,7 +154,7 @@
 }
 
 func (n *Node) HasAttr(k string) bool {
-	for _, a := range n.Attrs {
+	for _, a := range n.DomSubtree.Attr {
 		if a.Key == k {
 			return true
 		}