ref: 62b73b4e51b6d2db873956a9df9671e9cc2116c4
parent: 7c284bdddd481c95525f88e1a989bd512088b4a2
author: Philip Silva <philip.silva@protonmail.com>
date: Sat Jan 8 21:25:07 EST 2022
more up-to-date css lib
--- a/browser/browser_test.go
+++ b/browser/browser_test.go
@@ -3,7 +3,6 @@
import (
"9fans.net/go/draw"
"fmt"
- "github.com/chris-ramon/douceur/css"
"github.com/mjl-/duit"
"github.com/psilva261/opossum/browser/duitx"
"github.com/psilva261/opossum/logger"
@@ -69,11 +68,11 @@
h3 := nt.Find("h3") m := style.Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]style.Declaration),
}
- m.Declarations["display"] = css.Declaration{- Property: "display",
- Value: d,
+ m.Declarations["display"] = style.Declaration{+ Prop: "display",
+ Val: d,
}
h1.Map = m
h2.Map = m
--- a/browser/fs/experimental.go
+++ b/browser/fs/experimental.go
@@ -197,7 +197,7 @@
var v string
for p, d := range st.cs.Declarations { if p == k {- v = d.Value
+ v = d.Val
}
}
return []byte(v)
--- a/go.mod
+++ b/go.mod
@@ -8,10 +8,6 @@
replace github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f => github.com/psilva261/duit v0.0.0-20210802155600-7e8fedefa7ba
-exclude github.com/aymerick/douceur v0.1.0
-
-exclude github.com/aymerick/douceur v0.2.0
-
exclude github.com/hanwen/go-fuse v1.0.0
exclude github.com/hanwen/go-fuse/v2 v2.0.3
@@ -19,12 +15,11 @@
require (
9fans.net/go v0.0.2
github.com/andybalholm/cascadia v1.3.1
- github.com/chris-ramon/douceur v0.2.1-0.20160603235419-f3463056cd52
- github.com/gorilla/css v1.0.0 // indirect
github.com/knusbaum/go9p v1.18.0
github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f
github.com/srwiley/oksvg v0.0.0-20211120171407-1837d6608d8c
github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780
+ github.com/tdewolff/parse/v2 v2.5.26
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8
golang.org/x/text v0.3.7
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,6 @@
github.com/Plan9-Archive/libauth v0.0.0-20180917063427-d1ca9e94969d/go.mod h1:UKp8dv9aeaZoQFWin7eQXtz89iHly1YAFZNn3MCutmQ=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
-github.com/chris-ramon/douceur v0.2.1-0.20160603235419-f3463056cd52 h1:xJWyi77j4VQwdeo6bO3wQSQ7o7yVwEM0ZvwXpyKHZZ8=
-github.com/chris-ramon/douceur v0.2.1-0.20160603235419-f3463056cd52/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
@@ -10,8 +8,6 @@
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/fhs/mux9p v0.3.1 h1:x1UswUWZoA9vrA02jfisndCq3xQm+wrQUxUt5N99E08=
github.com/fhs/mux9p v0.3.1/go.mod h1:F4hwdenmit0WDoNVT2VMWlLJrBVCp/8UhzJa7scfjEQ=
-github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
-github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/knusbaum/go9p v1.18.0 h1:/Y67RNvNKX1ZV1IOdnO1lIetiF0X+CumOyvEc0011GI=
github.com/knusbaum/go9p v1.18.0/go.mod h1:HtMoJKqZUe1Oqag5uJqG5RKQ9gWPSP+wolsnLLv44r8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -27,6 +23,10 @@
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/tdewolff/parse/v2 v2.5.26 h1:a/q3lwDCi4GIQ+sSbs4UOHuObhqp8GHAhfqop/zDyQQ=
+github.com/tdewolff/parse/v2 v2.5.26/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
+github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
+github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
--- a/nodes/nodes.go
+++ b/nodes/nodes.go
@@ -3,7 +3,6 @@
import (
"bytes"
"fmt"
- "github.com/chris-ramon/douceur/css"
"github.com/psilva261/opossum/logger"
"github.com/psilva261/opossum/style"
"golang.org/x/net/html"
@@ -30,7 +29,7 @@
// First applies the parent style and at the end the local style attribute's style is attached.
func NewNodeTree(doc *html.Node, ps style.Map, nodeMap map[*html.Node]style.Map, parent *Node) (n *Node) { ncs := style.Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]style.Declaration),
}
ncs = ps.ApplyChildStyle(ncs, false)
@@ -58,9 +57,9 @@
n.Wrappable = doc.Type == html.TextNode || doc.Data == "span" // TODO: probably this list needs to be extended
if doc.Type == html.TextNode {n.Text = filterText(doc.Data)
- n.Map.Declarations["display"] = css.Declaration{- Property: "display",
- Value: "inline",
+ n.Map.Declarations["display"] = style.Declaration{+ Prop: "display",
+ Val: "inline",
}
}
i := 0
@@ -395,7 +394,7 @@
if len(n.Map.Declarations) > 0 {l := make([]string, 0, 2)
for k, d := range n.Map.Declarations {- s := fmt.Sprintf("%v=%v", k, d.Value)+ s := fmt.Sprintf("%v=%v", k, d.Val) if d.Important {s += "!"
}
--- a/opossum_test.go
+++ /dev/null
@@ -1,16 +1,0 @@
-package opossum
-
-import (
- "testing"
-
- "github.com/chris-ramon/douceur/parser"
-)
-
-// aymerick douceur issues #6
-func TestInfiniteLoop(t *testing.T) {- parser.Parse(`
-@media ( __desktop ) {- background-color: red;
-}
-`)
-}
--- /dev/null
+++ b/style/css.go
@@ -1,0 +1,121 @@
+package style
+
+import (
+ "fmt"
+ "github.com/psilva261/opossum/logger"
+ "github.com/tdewolff/parse/v2"
+ "github.com/tdewolff/parse/v2/css"
+ "io"
+ "strings"
+)
+
+type Sheet struct {+ Rules []Rule
+}
+
+type Rule struct {+ Prelude string
+ Selectors []Selector
+ Declarations []Declaration
+
+ Rules []Rule
+}
+
+type Selector struct {+ Val string
+}
+
+type Declaration struct {+ Important bool
+ Prop string
+ Val string
+}
+
+func Parse(rd io.Reader, inline bool) (s Sheet, err error) {+ s.Rules = make([]Rule, 0, 1000)
+ stack := make([]Rule, 0, 2)
+ selectors := make([]Selector, 0, 1)
+ p := css.NewParser(parse.NewInput(rd), inline)
+ if inline {+ stack = append(stack, Rule{})+ defer func() {+ s.Rules = append(s.Rules, stack[0])
+ }()
+ }
+ for {+ gt, _, data := p.Next()
+ switch gt {+ case css.ErrorGrammar:
+ if err := p.Err(); err == io.EOF {+ return s, nil
+ } else {+ return s, fmt.Errorf("next: %v", err)+ }
+ break
+ case css.QualifiedRuleGrammar:
+ sel := Selector{}+ for _, val := range p.Values() {+ sel.Val += string(val.Data)
+ }
+ selectors = append(selectors, sel)
+ case css.AtRuleGrammar, css.BeginAtRuleGrammar, css.BeginRulesetGrammar, css.DeclarationGrammar, css.CustomPropertyGrammar:
+ var d Declaration
+ if gt == css.BeginRulesetGrammar || gt == css.BeginAtRuleGrammar || gt == css.AtRuleGrammar {+ // TODO: why also gt == css.AtRuleGrammar? some sites crash otherwise
+ stack = append(stack, Rule{})+ }
+ r := &(stack[len(stack)-1])
+ if gt == css.DeclarationGrammar || gt == css.CustomPropertyGrammar {+ d.Prop = string(data)
+ }
+ if gt == css.BeginAtRuleGrammar {+ r.Prelude = string(data)
+ }
+ vals := p.Values()
+ for i, val := range vals {+ if gt == css.DeclarationGrammar || gt == css.CustomPropertyGrammar {+ if string(val.Data) == "!" && len(vals) == i+2 && string(vals[i+1].Data) == "important" {+ d.Important = true
+ break
+ } else {+ d.Val += string(val.Data)
+ }
+ } else if gt == css.BeginRulesetGrammar {+ if len(selectors) == 0 {+ sel := Selector{+ Val: string(val.Data),
+ }
+ selectors = append(selectors, sel)
+ } else {+ selectors[len(selectors)-1].Val += string(val.Data)
+ }
+ } else if gt == css.BeginAtRuleGrammar {+ r.Prelude += string(val.Data)
+ } else {+ }
+ }
+ if gt == css.DeclarationGrammar || gt == css.CustomPropertyGrammar {+ d.Val = strings.TrimSpace(d.Val)
+ r.Declarations = append(r.Declarations, d)
+ }
+ case css.EndRulesetGrammar, css.EndAtRuleGrammar:
+ var r Rule
+ if len(stack) == 1 {+ r, stack = stack[len(stack)-1], stack[:len(stack)-1]
+ r.Selectors = append([]Selector{}, selectors...)+ s.Rules = append(s.Rules, r)
+ } else {+ p := &(stack[len(stack)-2])
+ r, stack = stack[len(stack)-1], stack[:len(stack)-1]
+ r.Selectors = append([]Selector{}, selectors...)+ p.Rules = append(p.Rules, r)
+ }
+
+ selectors = make([]Selector, 0, 1)
+ case css.CommentGrammar:
+ default:
+ log.Errorf("unknown token type %+v", gt)+ }
+ }
+ return
+}
--- /dev/null
+++ b/style/css_test.go
@@ -1,0 +1,183 @@
+package style
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestParseInline(t *testing.T) {+ b := bytes.NewBufferString("color: red;")+ s, err := Parse(b, true)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ t.Logf("s: %+v", s)+ if len(s.Rules) != 1 {+ t.Fail()
+ }
+ r := s.Rules[0]
+ if len(r.Declarations) != 1 {+ t.Fail()
+ }
+ d := r.Declarations[0]
+ if d.Prop != "color" || d.Val != "red" {+ t.Fail()
+ }
+}
+
+func TestParseMin(t *testing.T) {+ b := bytes.NewBufferString(`
+ h1 {+ font-weight: bold;
+ font-size: 100px;
+ }
+ p, quote, a < b, div {+ color: grey !important;
+ }
+ :root {+ --emph: red;
+ --h: 10px;
+ }
+
+ b {+ color: var(--emph);
+ }
+ `)
+ s, err := Parse(b, false)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ t.Logf("s: %+v", s)+ if len(s.Rules) != 4 {+ t.Fatalf("%+v", s)+ }
+ r := s.Rules[0]
+ if len(r.Declarations) != 2 || len(r.Selectors) != 1 || r.Selectors[0].Val != "h1" {+ t.Fatalf("%+v", r)+ }
+ d := r.Declarations[0]
+ if d.Prop != "font-weight" || d.Val != "bold" || d.Important {+ t.Fatalf("%+v", d)+ }
+ r = s.Rules[1]
+ if len(r.Declarations) != 1 || len(r.Selectors) != 3 {+ t.Fatalf("%+v", r)+ }
+ d = r.Declarations[0]
+ if d.Prop != "color" || d.Val != "grey" || !d.Important {+ t.Fatalf("%+v", d)+ }
+ r = s.Rules[2]
+ if len(r.Declarations) != 2 || len(r.Selectors) != 1 || r.Selectors[0].Val != ":root" {+ t.Fatalf("%+v", r)+ }
+ d = r.Declarations[0]
+ if d.Prop != "--emph" || d.Val != "red" {+ t.Fatalf("%+v %+v", r, d)+ }
+}
+
+func TestParseMedia(t *testing.T) {+ b := bytes.NewBufferString(`
+ @media only screen and (max-width: 600px) {+ body {+ background-color: lightblue;
+ }
+ }
+ `)
+ s, err := Parse(b, false)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ t.Logf("s: %+v", s)+ t.Logf("s.Rules[0].Prelude: %+v", s.Rules[0].Prelude)+ //t.Logf("s.Rules[0].Prelude: %+v", s.Rules[0].Rules[0].Prelude)+ if len(s.Rules) != 1 {+ t.Fatalf("%+v", s)+ }
+ r := s.Rules[0]
+ if len(r.Declarations) != 0 || len(r.Selectors) > 0 {+ t.Fatalf("%+v", r)+ }
+ d := r.Rules[0].Declarations[0]
+ if d.Prop != "background-color" || d.Val != "lightblue" {+ t.Fatalf("%+v", d)+ }
+}
+
+func TestParseComment(t *testing.T) {+ b := bytes.NewBufferString(`
+ h1 {+ font-weight: bold;
+ font-size: 100px;
+ }
+ /* grey text */
+ p {+ color: grey !important;
+ }
+ `)
+ s, err := Parse(b, false)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ t.Logf("s: %+v", s)+ if len(s.Rules) != 2 {+ t.Fatalf("%v", s)+ }
+ r := s.Rules[0]
+ if len(r.Declarations) != 2 || r.Selectors[0].Val != "h1" {+ t.Fatalf("%v", r)+ }
+ d := r.Declarations[0]
+ if d.Prop != "font-weight" || d.Val != "bold" {+ t.Fatalf("%v", d)+ }
+ r = s.Rules[1]
+ if len(r.Declarations) != 1 || r.Selectors[0].Val != "p" {+ t.Fatalf("%v", r)+ }
+ d = r.Declarations[0]
+ if d.Prop != "color" || d.Val != "grey" || !d.Important {+ t.Fatalf("%v", d)+ }
+}
+
+func TestParseQual(t *testing.T) {+ b := bytes.NewBufferString(`
+ h1 {+ font-weight: bold;
+ font-size: 100px;
+ }
+ p {+ color: grey !important;
+ }
+ a[href] {+ color: blue;
+ margin-right: 2px;
+ }
+ `)
+ s, err := Parse(b, false)
+ if err != nil {+ t.Fatalf("%v", err)+ }
+ t.Logf("s: %+v", s)+ if len(s.Rules) != 3 {+ t.Fail()
+ }
+ r := s.Rules[0]
+ if len(r.Declarations) != 2 || r.Selectors[0].Val != "h1" {+ t.Fail()
+ }
+ d := r.Declarations[0]
+ if d.Prop != "font-weight" || d.Val != "bold" {+ t.Fail()
+ }
+ r = s.Rules[2]
+ if len(r.Declarations) != 2 || r.Selectors[0].Val != "a[href]" {+ t.Fatalf("%+v", r)+ }
+ d = r.Declarations[0]
+ if d.Prop != "color" || d.Val != "blue" {+ t.Fail()
+ }
+}
--- a/style/experimental.go
+++ b/style/experimental.go
@@ -3,7 +3,6 @@
import (
"9fans.net/go/draw"
"fmt"
- "github.com/chris-ramon/douceur/css"
"github.com/mjl-/duit"
"github.com/psilva261/opossum"
"github.com/psilva261/opossum/img"
@@ -20,10 +19,10 @@
}
var TextNode = Map{- Declarations: map[string]css.Declaration{- "display": css.Declaration{- Property: "display",
- Value: "inline",
+ Declarations: map[string]Declaration{+ "display": Declaration{+ Prop: "display",
+ Val: "inline",
},
},
}
@@ -62,7 +61,7 @@
func (cs Map) backgroundColor() (c draw.Color, ok bool) {d, ok := cs.Declarations["background-color"]
if ok {- c, ok = colorHex(d.Value)
+ c, ok = colorHex(d.Val)
if !ok {return
}
@@ -70,7 +69,7 @@
}
d, ok = cs.Declarations["background"]
if ok {- c, ok = colorHex(d.Value)
+ c, ok = colorHex(d.Val)
if !ok {return
}
@@ -99,7 +98,7 @@
if !ok {return
}
- v := strings.TrimSpace(d.Value)
+ v := strings.TrimSpace(d.Val)
if strings.HasPrefix(v, "linear-gradient(") { v = strings.TrimPrefix(v, "linear-gradient(") } else {@@ -155,8 +154,8 @@
return draw.Color(cc)
}
-func backgroundImageUrl(decl css.Declaration) (url string, ok bool) {- if v := decl.Value; strings.Contains(v, "url(") && strings.Contains(v, ")") {+func backgroundImageUrl(decl Declaration) (url string, ok bool) {+ if v := decl.Val; strings.Contains(v, "url(") && strings.Contains(v, ")") {v = strings.ReplaceAll(v, `"`, "")
v = strings.ReplaceAll(v, `'`, "")
from := strings.Index(v, "url(")--- a/style/experimental_test.go
+++ b/style/experimental_test.go
@@ -2,7 +2,6 @@
import (
"9fans.net/go/draw"
- "github.com/chris-ramon/douceur/css"
"github.com/psilva261/opossum/logger"
"testing"
)
@@ -15,8 +14,8 @@
suffix := ""
for _, quote := range []string{"", "'", `"`} {url := "/foo.png"
- decl := css.Declaration{- Value: "url(" + quote + url + quote + ")" + suffix,+ decl := Declaration{+ Val: "url(" + quote + url + quote + ")" + suffix,}
imgUrl, ok := backgroundImageUrl(decl)
if !ok {@@ -36,12 +35,12 @@
for _, k := range []string{"background", "background-color"} { m := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
for hex, d := range colors {- m.Declarations[k] = css.Declaration{- Property: k,
- Value: hex,
+ m.Declarations[k] = Declaration{+ Prop: k,
+ Val: hex,
}
if b, ok := m.backgroundColor(); !ok || b != d {@@ -59,11 +58,11 @@
}
for v, cc := range values { m := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
- m.Declarations["background"] = css.Declaration{- Property: "background",
- Value: v,
+ m.Declarations["background"] = Declaration{+ Prop: "background",
+ Val: v,
}
c, ok := m.backgroundGradient()
if !ok {--- a/style/stylesheets.go
+++ b/style/stylesheets.go
@@ -5,8 +5,6 @@
"bytes"
"fmt"
"github.com/andybalholm/cascadia"
- "github.com/chris-ramon/douceur/css"
- "github.com/chris-ramon/douceur/parser"
"github.com/mjl-/duit"
"github.com/psilva261/opossum/logger"
"golang.org/x/image/colornames"
@@ -25,8 +23,8 @@
var dui *duit.DUI
var availableFontNames []string
-var rMinWidth = regexp.MustCompile(`min-width: (\d+)(px|em|rem)`)
-var rMaxWidth = regexp.MustCompile(`max-width: (\d+)(px|em|rem)`)
+var rMinWidth = regexp.MustCompile(`min-width:\s*(\d+)(px|em|rem)`)
+var rMaxWidth = regexp.MustCompile(`max-width:\s*(\d+)(px|em|rem)`)
const FontBaseSize = 11.0
@@ -118,20 +116,20 @@
}
m = make(map[*html.Node]Map)
for n, rs := range mr {- ds := make(map[string]css.Declaration)
+ ds := make(map[string]Declaration)
for _, r := range rs { for _, d := range r.Declarations {- if exist, ok := ds[d.Property]; ok && smaller(*d, exist) {+ if exist, ok := ds[d.Prop]; ok && smaller(d, exist) {continue
}
- if strings.HasPrefix(d.Value, "var(") {- v := strings.TrimPrefix(d.Value, "var(")+ if strings.HasPrefix(d.Val, "var(") {+ v := strings.TrimPrefix(d.Val, "var(")v = strings.TrimSuffix(v, ")")
if vv, ok := rv[v]; ok {- d.Value = vv
+ d.Val = vv
}
}
- ds[d.Property] = *d
+ ds[d.Prop] = d
}
}
m[n] = Map{Declarations: ds}@@ -139,46 +137,37 @@
return
}
-func smaller(d, dd css.Declaration) bool {+func smaller(d, dd Declaration) bool {return dd.Important
}
func compile(v string) (cs cascadia.Selector, err error) {- l := strings.Split(v, " ")
- for _, s := range l {- s = strings.TrimSpace(s)
- if strings.HasSuffix(s, ":") {- // TODO: selectors like .selector: would crash otherwise
- err = fmt.Errorf("unsupported selector: %v", s)- return
- }
- }
return cascadia.Compile(v)
}
-func FetchNodeRules(doc *html.Node, cssText string, windowWidth int) (m map[*html.Node][]*css.Rule, rVars map[string]string, err error) {- m = make(map[*html.Node][]*css.Rule)
+func FetchNodeRules(doc *html.Node, cssText string, windowWidth int) (m map[*html.Node][]Rule, rVars map[string]string, err error) {+ m = make(map[*html.Node][]Rule)
rVars = make(map[string]string)
- s, err := parser.Parse(cssText)
+ s, err := Parse(strings.NewReader(cssText), false)
if err != nil {- return nil, nil, fmt.Errorf("douceur parse: %w", err)+ return nil, nil, fmt.Errorf("parse: %w", err)}
- processRule := func(m map[*html.Node][]*css.Rule, r *css.Rule) (err error) {+ processRule := func(m map[*html.Node][]Rule, r Rule) (err error) { for _, sel := range r.Selectors {- if sel.Value == ":root" {+ if sel.Val == ":root" { for _, d := range r.Declarations {- rVars[d.Property] = d.Value
+ rVars[d.Prop] = d.Val
}
}
- cs, err := compile(sel.Value)
+ cs, err := compile(sel.Val)
if err != nil {- log.Printf("cssSel compile %v: %v", sel.Value, err)+ log.Printf("cssSel compile %v: %v", sel.Val, err)continue
}
for _, el := range cascadia.QueryAll(doc, cs) {existing, ok := m[el]
if !ok {- existing = make([]*css.Rule, 0, 3)
+ existing = make([]Rule, 0, 3)
}
existing = append(existing, r)
m[el] = existing
@@ -233,13 +222,13 @@
}
type Map struct {- Declarations map[string]css.Declaration
+ Declarations map[string]Declaration
DomTree `json:"-"`
}
func NewMap(n *html.Node) Map { s := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
for _, a := range n.Attr {@@ -248,8 +237,13 @@
if !strings.HasSuffix(v, ";") {v += ";"
}
- decls, err := parser.ParseDeclarations(v)
+ st, err := Parse(strings.NewReader(v), true)
+ var decls []Declaration
+ if len(st.Rules) > 0 {+ decls = st.Rules[0].Declarations
+ }
+
if err != nil { log.Printf("could not parse '%v'", a.Val)break
@@ -256,7 +250,7 @@
}
for _, d := range decls {- s.Declarations[d.Property] = *d
+ s.Declarations[d.Prop] = d
}
} else if a.Key == "height" || a.Key == "width" {v := a.Val
@@ -265,14 +259,14 @@
v += "px"
}
- s.Declarations[a.Key] = css.Declaration{- Property: a.Key,
- Value: v,
+ s.Declarations[a.Key] = Declaration{+ Prop: a.Key,
+ Val: v,
}
} else if a.Key == "bgcolor" {- s.Declarations["background-color"] = css.Declaration{- Property: "background-color",
- Value: a.Val,
+ s.Declarations["background-color"] = Declaration{+ Prop: "background-color",
+ Val: a.Val,
}
}
}
@@ -281,7 +275,7 @@
}
func (cs Map) ApplyChildStyle(ccs Map, copyAll bool) (res Map) {- res.Declarations = make(map[string]css.Declaration)
+ res.Declarations = make(map[string]Declaration)
for k, v := range cs.Declarations { switch k {@@ -296,7 +290,7 @@
}
// overwrite with higher prio child props
for k, v := range ccs.Declarations {- if v.Value == "inherit" {+ if v.Val == "inherit" {continue
}
res.Declarations[k] = v
@@ -361,21 +355,21 @@
func (cs Map) FontSize() float64 {fs, ok := cs.Declarations["font-size"]
- if !ok || fs.Value == "" {+ if !ok || fs.Val == "" {return FontBaseSize
}
- if len(fs.Value) <= 2 {- log.Printf("error parsing font size %v", fs.Value)+ if len(fs.Val) <= 2 {+ log.Printf("error parsing font size %v", fs.Val)return FontBaseSize
}
- numStr := fs.Value[0 : len(fs.Value)-2]
+ numStr := fs.Val[0 : len(fs.Val)-2]
f, err := strconv.ParseFloat(numStr, 64)
if err != nil {- log.Printf("error parsing font size %v", fs.Value)+ log.Printf("error parsing font size %v", fs.Val)return FontBaseSize
}
- if strings.HasSuffix(fs.Value, "em") {+ if strings.HasSuffix(fs.Val, "em") {f *= FontBaseSize
}
return f
@@ -388,7 +382,7 @@
func (cs Map) Color() draw.Color { if d, ok := cs.Declarations["color"]; ok {- if h, ok := colorHex(d.Value); ok {+ if h, ok := colorHex(d.Val); ok {c := draw.Color(h)
return c
}
@@ -486,13 +480,13 @@
func (cs Map) IsInline() bool {propVal, ok := cs.Declarations["float"]
- if ok && propVal.Value == "left" {+ if ok && propVal.Val == "left" {return true
}
propVal, ok = cs.Declarations["display"]
if ok {- return propVal.Value == "inline" ||
- propVal.Value == "inline-block"
+ return propVal.Val == "inline" ||
+ propVal.Val == "inline-block"
}
return false
}
@@ -499,21 +493,21 @@
func (cs Map) IsDisplayNone() bool {propVal, ok := cs.Declarations["display"]
- if ok && propVal.Value == "none" {+ if ok && propVal.Val == "none" {return true
}
/*propVal, ok = cs.Declarations["position"]
- if ok && propVal.Value == "fixed" {+ if ok && propVal.Val == "fixed" {return true
}*/
propVal, ok = cs.Declarations["clip"]
- if ok && strings.ReplaceAll(propVal.Value, " ", "") == "rect(1px,1px,1px,1px)" {+ if ok && strings.ReplaceAll(propVal.Val, " ", "") == "rect(1px,1px,1px,1px)" {return true
}
propVal, ok = cs.Declarations["width"]
- if ok && propVal.Value == "1px" {+ if ok && propVal.Val == "1px" {propVal, ok = cs.Declarations["height"]
- if ok && propVal.Value == "1px" {+ if ok && propVal.Val == "1px" {return true
}
}
@@ -523,7 +517,7 @@
func (cs Map) IsFlex() bool {propVal, ok := cs.Declarations["display"]
if ok {- return propVal.Value == "flex"
+ return propVal.Val == "flex"
}
return false
}
@@ -531,7 +525,7 @@
func (cs Map) IsFlexDirectionRow() bool {propVal, ok := cs.Declarations["flex-direction"]
if ok {- switch propVal.Value {+ switch propVal.Val {case "row":
return true
case "column":
@@ -545,7 +539,7 @@
// margin-top, ...-right, ...-bottom, ...-left.
func (cs *Map) Tlbr(key string) (s duit.Space, err error) { if all, ok := cs.Declarations[key]; ok {- parts := strings.Split(all.Value, " ")
+ parts := strings.Split(all.Val, " ")
nums := make([]int, len(parts))
for i, p := range parts { if f, _, err := length(cs, p); err == nil {@@ -702,7 +696,7 @@
func (cs *Map) Height() int {d, ok := cs.Declarations["height"]
if ok {- f, _, err := length(cs, d.Value)
+ f, _, err := length(cs, d.Val)
if err != nil { log.Errorf("cannot parse height: %v", err)}
@@ -715,7 +709,7 @@
w := cs.width()
if w > 0 { if d, ok := cs.Declarations["max-width"]; ok {- f, _, err := length(&cs, d.Value)
+ f, _, err := length(&cs, d.Val)
if err != nil { log.Errorf("cannot parse width: %v", err)}
@@ -730,7 +724,7 @@
func (cs Map) width() int {d, ok := cs.Declarations["width"]
if ok {- f, _, err := length(&cs, d.Value)
+ f, _, err := length(&cs, d.Val)
if err != nil { log.Errorf("cannot parse width: %v", err)}
@@ -762,7 +756,7 @@
if !ok {return ""
}
- return d.Value
+ return d.Val
}
func (cs *Map) CssPx(propName string) (l int, err error) {@@ -770,7 +764,7 @@
if !ok { return 0, fmt.Errorf("property doesn't exist")}
- f, _, err := length(cs, d.Value)
+ f, _, err := length(cs, d.Val)
if err != nil {return 0, err
}
@@ -779,8 +773,8 @@
}
func (cs Map) SetCss(k, v string) {- cs.Declarations[k] = css.Declaration{- Property: k,
- Value: v,
+ cs.Declarations[k] = Declaration{+ Prop: k,
+ Val: v,
}
}
--- a/style/stylesheets_test.go
+++ b/style/stylesheets_test.go
@@ -1,7 +1,6 @@
package style
import (
- "github.com/chris-ramon/douceur/css"
"github.com/mjl-/duit"
"github.com/psilva261/opossum/logger"
"golang.org/x/net/html"
@@ -103,10 +102,10 @@
if w == 400 {_ = m[body][0]
- if v := m[body][0].Declarations[0].Value; v != "lightblue" {+ if v := m[body][0].Declarations[0].Val; v != "lightblue" { t.Fatalf("%v", v)}
- t.Logf("%v", m[body][0].Name)+ t.Logf("%v", m[body][0]) } else { if _, ok := m[body]; ok { t.Fatalf("body ok")@@ -197,7 +196,7 @@
h2 := grep(doc, "h2")
m := NewMap(h2)
- if m.Declarations["color"].Value != "green" {+ if m.Declarations["color"].Val != "green" { t.Errorf("%+v", m)}
}
@@ -220,10 +219,10 @@
}
func TestSmaller(t *testing.T) {- d := css.Declaration{+ d := Declaration{Important: false,
}
- dd := css.Declaration{+ dd := Declaration{Important: true,
}
if !smaller(d, dd) {@@ -233,18 +232,18 @@
func TestApplyChildStyleInherit(t *testing.T) { parent := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
- parent.Declarations["height"] = css.Declaration{- Property: "height",
- Value: "80px",
+ parent.Declarations["height"] = Declaration{+ Prop: "height",
+ Val: "80px",
}
child := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
res := parent.ApplyChildStyle(child, true)
- if v := res.Declarations["height"].Value; v != "80px" {+ if v := res.Declarations["height"].Val; v != "80px" {t.Fatalf(v)
}
}
@@ -251,22 +250,22 @@
func TestApplyChildStyleInherit2(t *testing.T) { parent := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
child := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
- parent.Declarations["font-size"] = css.Declaration{- Property: "font-size",
- Value: "12pt",
+ parent.Declarations["font-size"] = Declaration{+ Prop: "font-size",
+ Val: "12pt",
}
- child.Declarations["font-size"] = css.Declaration{- Property: "font-size",
- Value: "inherit",
+ child.Declarations["font-size"] = Declaration{+ Prop: "font-size",
+ Val: "inherit",
}
res := parent.ApplyChildStyle(child, true)
- if v := res.Declarations["font-size"].Value; v != "12pt" {+ if v := res.Declarations["font-size"].Val; v != "12pt" {t.Fatalf(v)
}
}
@@ -339,11 +338,11 @@
}
for v, exp := range cases { m := Map{- Declarations: make(map[string]css.Declaration),
+ Declarations: make(map[string]Declaration),
}
- m.Declarations["margin"] = css.Declaration{- Property: "margin",
- Value: v,
+ m.Declarations["margin"] = Declaration{+ Prop: "margin",
+ Val: v,
}
s, err := m.Tlbr("margin") if err != nil {@@ -403,7 +402,7 @@
}
d := nm[b]
t.Logf("d=%+v", d)- if d.Declarations["color"].Value != "red" {- t.Fail()
+ if d.Declarations["color"].Val != "red" {+ t.Fatalf("%+v", d.Declarations)}
}
--
⑨