CSSHTML#
The boxes and glue csshtml package is made to combine CSS style instructions and HTML text and return a tree data structures which makes it easy to find the style information.
The main CSS struct looks like this:
type CSS struct {
Pages map[string]Page
FileFinder func(string) (string, error)
FontFaces []FontFace
}
See the package documentation for details.
Attribute resolving#
cs := csshtml.NewCSSParser()
cs.AddCSSText(`
p {
font-weight: bold;
}
`)
gqd, err := cs.ProcessHTMLChunk(`<p foo="bar" style="border: 1pt solid black;">hello world</p>`)
if err != nil {
return err
}
gqd.Find("p").Each(func(i int, sel *goquery.Selection) {
n := sel.Get(0) // a golang.org/x/net/html Node
for _, attr := range n.Attr {
fmt.Println(attr.Key, attr.Val)
}
resolved, newAttrs := csshtml.ResolveAttributes(n.Attr)
fmt.Println("-----------")
fmt.Println(resolved)
fmt.Println("-----------")
fmt.Println(newAttrs)
})
returns
foo bar
style border: 1pt solid black;
!font-weight bold
!border 1pt solid black
-----------
map[
border-bottom-color:black
border-bottom-style:solid
border-bottom-width:1pt
border-left-color:black
border-left-style:solid
border-left-width:1pt
border-right-color:black
border-right-style:solid
border-right-width:1pt
border-top-color:black
border-top-style:solid
border-top-width:1pt
font-weight:bold
]
-----------
[{ foo bar}
{ style border: 1pt solid black;}
{ !font-weight bold}
{ *font-weight bold}
{ *border 1pt solid black}
{ *border-top-style solid}
{ *border-top-width 1pt}
{ *border-top-color black}
{ *border-right-style solid}
{ *border-right-width 1pt}
{ *border-right-color black}
{ *border-bottom-style solid}
{ *border-bottom-width 1pt}
{ *border-bottom-color black}
{ *border-left-style solid}
{ *border-left-width 1pt}
{ *border-left-color black}
]
Explanation: The original attributes in the HTML tree (foo
and style
) stay unchanged in the tree. Style instructions (from CSS text or from the style attribute) are added to the node prefixed with a exclamation mark, otherwise unchanged.
Calling csshtml.ResolveAttributes()
on these attributes returns two values: a map (string -> string) of the resolved attributes and a slice of resolved attributes. Resolving means in this case turning an instruction such as margin: 1em 2em
into margin-top: 1em
, margin-right: 2em
, margin-bottom: 1em
and margin-left: 2em
.
The second argument contains a slice of attributes with prefixed names: original attributes have no prefix, unresolved style attributes have an !
prefix and resolved styles a *
.
Using fonts#
cs := csshtml.NewCSSParser()
cs.AddCSSText(`
@font-face {
font-family: "MetaPro";
src: url("../fonts/ff-metapro-book.otf");
font-weight: bold;
}
@font-face {
font-family: "MetaPro";
src: url("../fonts/ff-metapro-normal.otf");
}
`)
for _, ff := range cs.FontFaces {
fmt.Println(ff.Family, ff.Source[0].URI, ff.Weight)
}