Skip to content

Commit

Permalink
#8 Use list for storing rules and properties
Browse files Browse the repository at this point in the history
  • Loading branch information
vanng822 committed Apr 26, 2019
1 parent 39923e4 commit 0a8180e
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 21 deletions.
38 changes: 30 additions & 8 deletions premailer/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package premailer

import (
"fmt"
"strings"

"github.com/PuerkitoBio/goquery"
"github.com/vanng822/css"
"sort"
"strings"
)

type void struct{}

type elementRules struct {
element *goquery.Selection
rules []*styleRule
Expand All @@ -17,33 +19,53 @@ type elementRules struct {
func (er *elementRules) inline() {
inline, _ := er.element.Attr("style")

var inlineStyles map[string]*css.CSSStyleDeclaration
inlineStyles := make([]*css.CSSStyleDeclaration, 0)
if inline != "" {
inlineStyles = css.ParseBlock(inline)
}

// we collect all occurences
orders := make([]string, 0)
styles := make(map[string]string)
for _, rule := range er.rules {
for prop, s := range rule.styles {
for _, s := range rule.styles {
prop := s.Property
styles[prop] = s.Value
orders = append(orders, prop)
}
}

if len(inlineStyles) > 0 {
for prop, s := range inlineStyles {
for _, s := range inlineStyles {
prop := s.Property
styles[prop] = s.Value
orders = append(orders, prop)
}
}

// now collect the order of property
// each prop will be unique and the last one
// should have the highest priority
// We could inline them all but this will make output cleaner
props := make([]string, 0)
seen := make(map[string]void)
for i := len(orders) - 1; i >= 0; i-- {
prop := orders[i]
if _, ok := seen[prop]; !ok {
seen[prop] = void{}
props = append(props, prop)
}
}

final := make([]string, 0, len(styles))
for p, v := range styles {
for i := len(props) - 1; i >= 0; i-- {
p := props[i]
v := styles[p]
final = append(final, fmt.Sprintf("%s:%s", p, v))
if er.cssToAttributes {
er.style_to_basic_html_attribute(p, v)
}
}

sort.Strings(final)
style := strings.Join(final, ";")
if style != "" {
er.element.SetAttr("style", style)
Expand Down
10 changes: 5 additions & 5 deletions premailer/premailer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ func (pr *premailer) sortRules() {
pr.leftover = append(pr.leftover, rule)
continue
}
normalStyles := make(map[string]*css.CSSStyleDeclaration)
importantStyles := make(map[string]*css.CSSStyleDeclaration)
normalStyles := make([]*css.CSSStyleDeclaration, 0)
importantStyles := make([]*css.CSSStyleDeclaration, 0)

for prop, s := range rule.Style.Styles {
for _, s := range rule.Style.Styles {
if s.Important == 1 {
importantStyles[prop] = s
importantStyles = append(importantStyles, s)
} else {
normalStyles[prop] = s
normalStyles = append(normalStyles, s)
}
}

Expand Down
2 changes: 1 addition & 1 deletion premailer/premailer_from_bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestPremailerBasicHTMLBytes(t *testing.T) {
result_html, err := p.Transform()
assert.Nil(t, err)

assert.Contains(t, result_html, "<h1 style=\"color:red;width:50px\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h1 style=\"width:50px;color:red\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h2 style=\"vertical-align:top\" valign=\"top\">There</h2>")
assert.Contains(t, result_html, "<h3 style=\"text-align:right\" align=\"right\">Hello</h3>")
assert.Contains(t, result_html, "<p><strong style=\"text-decoration:none\">Yes!</strong></p>")
Expand Down
2 changes: 1 addition & 1 deletion premailer/premailer_from_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func TestBasicHTMLFromFile(t *testing.T) {
result_html, err := p.Transform()
assert.Nil(t, err)

assert.Contains(t, result_html, "<h1 style=\"color:red;width:50px\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h1 style=\"width:50px;color:red\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h2 style=\"vertical-align:top\" valign=\"top\">There</h2>")
assert.Contains(t, result_html, "<h3 style=\"text-align:right\" align=\"right\">Hello</h3>")
assert.Contains(t, result_html, "<p><strong style=\"text-decoration:none\">Yes!</strong></p>")
Expand Down
4 changes: 2 additions & 2 deletions premailer/premailer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestBasicHTML(t *testing.T) {
result_html, err := p.Transform()
assert.Nil(t, err)

assert.Contains(t, result_html, "<h1 style=\"color:red;width:50px\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h1 style=\"width:50px;color:red\" width=\"50\">Hi!</h1>")
assert.Contains(t, result_html, "<h2 style=\"vertical-align:top\" valign=\"top\">There</h2>")
assert.Contains(t, result_html, "<h3 style=\"text-align:right\" align=\"right\">Hello</h3>")
assert.Contains(t, result_html, "<p><strong style=\"text-decoration:none\">Yes!</strong></p>")
Expand Down Expand Up @@ -275,7 +275,7 @@ func TestWithMediaRule(t *testing.T) {
assert.Contains(t, result_html, "@media all and (min-width: 62em){")
assert.Contains(t, result_html, "font-size: 55px !important;")
assert.Contains(t, result_html, "line-height: 60px !important;")
assert.Contains(t, result_html, "padding-bottom: 5px !important;")
assert.Contains(t, result_html, "padding-bottom: 5px !important")
assert.Contains(t, result_html, "padding-top: 0 !important")
}

Expand Down
2 changes: 1 addition & 1 deletion premailer/style_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import (
type styleRule struct {
specificity *specificity
selector string
styles map[string]*css.CSSStyleDeclaration
styles []*css.CSSStyleDeclaration
}
6 changes: 3 additions & 3 deletions premailer/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (

func copyRule(selector string, rule *css.CSSRule) *css.CSSRule {
// copy rule for each selector
styles := make(map[string]*css.CSSStyleDeclaration)
for prop, s := range rule.Style.Styles {
styles[prop] = css.NewCSSStyleDeclaration(s.Property, s.Value, s.Important)
styles := make([]*css.CSSStyleDeclaration, 0)
for _, s := range rule.Style.Styles {
styles = append(styles, css.NewCSSStyleDeclaration(s.Property, s.Value, s.Important))
}
copiedStyle := css.CSSStyleRule{SelectorText: selector, Styles: styles}
copiedRule := &css.CSSRule{Type: rule.Type, Style: copiedStyle}
Expand Down

0 comments on commit 0a8180e

Please sign in to comment.