style

package
v0.1.0-experimental.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2021 License: BSD-3-Clause Imports: 7 Imported by: 0

README

HTML/CSS Styling

We strive to separate content from presentation. In typesetting, this is probably an impossible claim, but we'll try anyway. Presentation is governed with CSS (Cascading Style Sheets). CSS uses a box model more complex than that of the TeX typesetting system and is well described here:

https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model

If you think about it: a typesetter using the HTML/CSS box model is effectively a browser with output type PDF. We therefore employ styling of HTML nodes like a web browser does. A good explanation of styling may be found in

https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/

We will produce a "styled tree", which associates HTML nodes with CSS styles. Given the HTML input

<html><head></head><body>
  <p>The quick brown fox jumps over the lazy dog.</p>
  <p id="world">Hello <b>World</b>!</p>
  <p>This is a test.</p>
</body>

and a style sheet like this:

p {
	margin-bottom: 10pt;
}
#world {
	padding-top: 20pt;
}

a styling engine wil produce a tree like this (simplified version – the real data structures are more involved):

styling

CSSOM is the "CSS Object Model", similar to the DOM for HTML.

Caveats

Browsers are large and complex pieces of software, a fact that implies that we should seek out where to reduce complexity. There is not very much open source Go code around for supporting us in implementing a styling engine, except the great work of https://godoc.org/github.com/andybalholm/cascadia. Therefore we will have to compromise on many features in order to complete this in a realistic time frame.

This package relies on just one non-standard external library: cascadia. CSS handling is de-coupled by introducing appropriate interfaces StyleSheet and Rule. Concrete implementations may be found in sub-packages of package style.

Status

This is a first draft. It is unstable and the API will change without notice. Please be patient.

Documentation

Overview

Package style provides functionality for CSS styling properties.

Status

This is a very first draft. It is unstable and the API will change without notice. Please be patient.

Overview

We strive to separate content from presentation. In typesetting, this is probably an impossible claim, but we'll try anyway. Presentation is governed with CSS (Cascading Style Sheets). CSS uses a box model more complex than TeX's, which is well described here:

https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model

If you think about it: a typesetter using the HTML/CSS box model is effectively a browser with output type PDF. Browsers are large and complex pieces of code, a fact that implies that we should seek out where to reduce complexity.

A good explanation of styling may be found in

https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/

CSSOM is the "CSS Object Model", similar to the DOM for HTML. There is not very much open source Go code around for supporting us in implementing a styling engine, except the great work of https://godoc.org/github.com/andybalholm/cascadia. Therefore we will have to compromise on many feature in order to complete this in a realistic time frame. For a reminder of why that is, refer to this discussion at stackoverflow: https://stackoverflow.com/questions/598841/how-to-get-started-building-a-web-browser.

The styling engine produces a tree data structure, called "styled tree". Different web browser implementations call it differentyl ("render tree", ...). We define appropriate interfaces to de-couple the styled tree implmentation from the styling engine. This may sound odd, as the styled tree is such a central data structure to the engine. However, we expect to use different implementations of styled trees, depending on wether it is used for print or for interactive use.

A concrete default implementations may be found in package dom.styledtree.

References

https://www.tutorialrepublic.com/css-reference/css3-properties.php
https://www.w3schools.com/css/css3_multiple_columns.asp
https://www.mediaevent.de/xhtml/kernattribute.html

BSD License

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of this software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Index

Constants

View Source
const (
	PGMargins   = "Margins"
	PGPadding   = "Padding"
	PGBorder    = "Border"
	PGDimension = "Dimension"
	PGDisplay   = "Display"
	PGRegion    = "Region"
	PGColor     = "Color"
	PGText      = "Text"
	PGX         = "X"
)

Symbolic names for string literals, denoting PropertyGroups.

Variables

This section is empty.

Functions

func ColorString

func ColorString(c color.Color) string

func GroupNameFromPropertyKey

func GroupNameFromPropertyKey(key string) string

GroupNameFromPropertyKey returns the style property group name for a style property. Example:

GroupNameFromPropertyKey("margin-top") => "Margins"

Unknown style property keys will return a group name of "X".

func IsCascading

func IsCascading(key string) bool

IsCascading returns wether the standard behaviour for a propery is to be inherited or not, i.e., a call to retrieve its value will cascade.

func T

func T() tracing.Trace

T traces to a global engine tracer.

Types

type Interf

type Interf func(*tree.Node) Styler

Interf is a mapper from a concrete tree node to an interface implementation for Styler. You can think of this function type as an adapter from a certain tree implementation to a styled tree.

type KeyValue

type KeyValue struct {
	Key   string
	Value Property
}

KeyValue is a container for a style property.

func SplitCompoundProperty

func SplitCompoundProperty(key string, value Property) ([]KeyValue, error)

SplitCompoundProperty splits up a shortcut property into its individual components. Returns a slice of key-value pairs representing the individual (fine grained) style properties. Example:

SplitCompountProperty("padding", "3px")

will return

"padding-top"    => "3px"
"padding-right"  => "3px"
"padding-bottom" => "3px"
"padding-left  " => "3px"

For the logic behind this, refer to e.g. https://www.w3schools.com/css/css_padding.asp .

type NodeCreator

type NodeCreator interface {
	StyleForHTMLNode(*html.Node) *tree.Node
	ToStyler(*tree.Node) Styler
	SetStyles(*tree.Node, *PropertyMap)
}

NodeCreator is a function to create a style node for a given HTML node. This interface is used to de-couple concrete implementations of styled trees from the building process of a styled tree. Starting with a CSS object model (CSSOM) an HTML parse tree has to be traversed and the CSS properites will be applied to each HTML node. Application of CSS styles to an HTML node will result in a styled tree node. NodeCreator is necessary to make this traversal and styled node creation independent from concrete implementations. The link between the styling algorithm and the concrete style tree implementation is a NodeCreator, which knows how to create a styled tree node from an HTML node and a given set of CSS styles.

type Property

type Property string

Property is a raw value for a CSS property. For example, with

color: black

a property value of "black" is set. The main purpose of wrapping the raw string value into type Property is to provide a set of convenient type conversion functions and other helpers.

const NullStyle Property = ""

NullStyle is an empty property value.

func DisplayPropertyForHTMLNode

func DisplayPropertyForHTMLNode(node *html.Node) Property

DisplayPropertyForHTMLNode returns the default `display` CSS property for an HTML node.

func GetUserAgentDefaultProperty

func GetUserAgentDefaultProperty(styler Styler, key string) Property

GetUserAgentDefaultProperty returns the user-agent default property for a given key.

func (Property) Color

func (p Property) Color() color.Color

TODO use standard palette

https://pkg.go.dev/github.com/AntoineAugusti/colors#StringToHexColor

func (Property) IsEmpty

func (p Property) IsEmpty() bool

IsEmpty checks wether a property is empty, i.e. the null-string.

func (Property) IsInherit

func (p Property) IsInherit() bool

IsInherit denotes if a property is of inheritence-type "inherit"

func (Property) IsInitial

func (p Property) IsInitial() bool

IsInitial denotes if a property is of inheritence-type "initial"

func (Property) String

func (p Property) String() string

type PropertyGroup

type PropertyGroup struct {
	Parent *PropertyGroup
	// contains filtered or unexported fields
}

PropertyGroup is a collection of propertes sharing a common topic. CSS knows a whole lot of properties. We split them up into organisatorial groups.

The mapping of property into groups is documented with GroupNameFromPropertyKey[...].

func NewPropertyGroup

func NewPropertyGroup(groupname string) *PropertyGroup

NewPropertyGroup creates a new empty property group, given its name.

func (*PropertyGroup) Add

func (pg *PropertyGroup) Add(key string, p Property)

Add a property's value. Does not overwrite an existing value, i.e., does nothing if a value is already set.

func (*PropertyGroup) Cascade

func (pg *PropertyGroup) Cascade(key string) *PropertyGroup

Cascade finds the ancesting PropertyGroup containing the given property-key.

func (*PropertyGroup) ForkOnProperty

func (pg *PropertyGroup) ForkOnProperty(key string, p Property, cascade bool) (*PropertyGroup, bool)

ForkOnProperty creates a new PropertyGroup, pre-filled with a given property. If 'cascade' is true, the new PropertyGroup will be linking to the ancesting PropertyGroup containing this property.

func (*PropertyGroup) Get

func (pg *PropertyGroup) Get(key string) (Property, bool)

Get a property's value.

Style property values are always converted to lower case.

func (*PropertyGroup) IsSet

func (pg *PropertyGroup) IsSet(key string) bool

IsSet is a predicated wether a property is set within this group.

func (*PropertyGroup) Name

func (pg *PropertyGroup) Name() string

Name returns the name of the property group. Once named (during construction, property groups may not be renamed.

func (*PropertyGroup) Properties

func (pg *PropertyGroup) Properties() []KeyValue

Properties returns all properties of a group.

func (*PropertyGroup) Set

func (pg *PropertyGroup) Set(key string, p Property)

Set a property's value. Overwrites an existing value, if present.

Style property values are always converted to lower case.

func (*PropertyGroup) String

func (pg *PropertyGroup) String() string

Stringer for property groups; used for debugging.

type PropertyMap

type PropertyMap struct {
	// contains filtered or unexported fields
}

PropertyMap holds CSS properties. nil is a legal (empty) property map. A property map is the entity styling a DOM node: a DOM node links to a property map, which contains zero or more property groups. Property maps may share property groups.

func InitializeDefaultPropertyValues

func InitializeDefaultPropertyValues(additionalProps []KeyValue) *PropertyMap

InitializeDefaultPropertyValues creates an internal data structure to hold all the default values for CSS properties. In real-world browsers these are the user-agent CSS values.

func NewPropertyMap

func NewPropertyMap() *PropertyMap

NewPropertyMap returns a new empty property map.

func (*PropertyMap) Add

func (pmap *PropertyMap) Add(key string, value Property)

Add adds a property to this property map, e.g.,

pm.Add("funny-margin", "big")

func (*PropertyMap) AddAllFromGroup

func (pmap *PropertyMap) AddAllFromGroup(group *PropertyGroup, overwrite bool) *PropertyMap

AddAllFromGroup transfers all style properties from a property group to a property map. If overwrite is set, existing style property values will be overwritten, otherwise only new values are set.

If the property map does not yet contain a group of this kind, it will simply set this group (instead of copying values).

func (*PropertyMap) GetPropertyValue

func (pmap *PropertyMap) GetPropertyValue(key string, node *tree.Node, styler Interf) Property

GetPropertyValue returns the property value for a given key. If the property is inherited, it may cascade.

func (*PropertyMap) Group

func (pmap *PropertyMap) Group(groupname string) *PropertyGroup

Group returns the property group for a group name or nil.

func (*PropertyMap) Property

func (pmap *PropertyMap) Property(key string) (Property, bool)

Property returns a style property value, together with an indicator wether it has been found in the properties map. No cascading is performed

func (*PropertyMap) Size

func (pmap *PropertyMap) Size() int

Size returns the number of property groups.

func (*PropertyMap) String

func (pmap *PropertyMap) String() string

type Styler

type Styler interface {
	HTMLNode() *html.Node
	Styles() *PropertyMap
	StylesCascade() Styler
}

Styler is an interface all concrete types of styled tree nodes will have to implement to be usable for layout, rendering, etc.

Directories

Path Synopsis
Package css provides functionality for CSS styling.
Package css provides functionality for CSS styling.
Package cssom provides functionality for CSS styling.
Package cssom provides functionality for CSS styling.
douceuradapter
Package douceuradapter is a concrete implementation of interface cssom.StyleSheet.
Package douceuradapter is a concrete implementation of interface cssom.StyleSheet.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL