ref: 4d0b99d04d24818c1b1d05ff49ce11b4c1131215
dir: /browser/fs/experimental.go/
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" "github.com/psilva261/opossum/style" "golang.org/x/net/html" ) // Node such that one obtains a file structure like // // /0 // /0/attrs // /0/geom // /0/html // /0/style // /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["geom"] = n.geom() cs["html"] = n.html() cs["style"] = Style{cs: &n.nt.Map} } 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) geom() fs.FSNode { return fs.NewDynamicFile( oFS.NewStat("geom", un, gn, 0666), func() (bs []byte) { var dt style.DomTree if dt = n.nt.Map.DomTree; dt == nil { return } r := dt.Rect() return []byte(fmt.Sprintf("%v,%v,%v,%v", r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)) }, ) } 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 } type Style struct { cs *style.Map } func (st Style) Stat() (s proto.Stat) { s = *oFS.NewStat("style", un, gn, 0500) s.Mode |= proto.DMDIR // qtype bits should be consistent with Stat mode. s.Qid.Qtype = uint8(s.Mode >> 24) return } func (st Style) WriteStat(s *proto.Stat) error { return nil } func (st Style) SetParent(p fs.Dir) { } func (st Style) Parent() fs.Dir { return nil } func (st Style) Children() (cs map[string]fs.FSNode) { log.Infof("Style#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 p, d := range st.cs.Declarations { if p == k { v = d.Val } } return []byte(v) }, ) } for p := range st.cs.Declarations { cs[p] = ff(p) } return }