cssom

package
v0.0.0-...-ae32867 Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2020 License: BSD-3-Clause Imports: 12 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 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. 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 (simpified 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. For a reminder of why that is, refer to https://www.youtube.com/watch?v=S68fcV09nGQ .

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 very first draft. It is unstable and the API will change without notice. Please be patient.

Documentation

Overview

Package cssom provides functionality for CSS styling.

Status

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

Overview

HTMLbook is the core DOM of our documents. Background for this decision can be found under https://www.balisage.net/Proceedings/vol10/print/Kleinfeld01/BalisageVol10-Kleinfeld01.html and http://radar.oreilly.com/2013/09/html5-is-the-future-of-book-authorship.html For an in-depth description of HTMLbook please refer to https://oreillymedia.github.io/HTMLBook/.

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.

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.

Further to consider:

https://godoc.org/github.com/ericchiang/css
https://golanglibs.com/search?q=css+parser&sort=top
https://www.mediaevent.de/xhtml/style.html

The styling component is difficult to document/describe without diagrams. Think about documenting with https://github.com/robertkrimen/godocdown.

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

This section is empty.

Variables

This section is empty.

Functions

func T

func T() tracing.Trace

T returns a global tracer. We trace to EngineTracer.

Types

type CSSOM

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

CSSOM is the "CSS Object Model", similar to the DOM for HTML. Our CSSOM consists of a set of stylesheets, each relevant for a sub-tree of the HTML parse tree. This sub-tree is called the "scope" of the stylesheet. Sub-trees are identified through the top node.

Stylesheets are wrapped into an internal rules tree.

func NewCSSOM

func NewCSSOM(additionalProperties []style.KeyValue) CSSOM

NewCSSOM creates an empty CSSOM. Clients are allowed to supply a map of additional/custom CSS property values. These may override values of the default ("user-agent") style sheet, or introduce completely new styling properties.

func (CSSOM) AddStylesForScope

func (cssom CSSOM) AddStylesForScope(scope *html.Node, css StyleSheet, source PropertySource) error

AddStylesForScope includes a stylesheet to a CSSOM and sets the scope for the stylesheet. If a stylesheet for the scope already exists, the styles are merged. css may be nil. If scope is nil then scope is the root (i.e., top-level content element) of a future document.

The stylsheet may not be nil. source hints to where the stylesheet comes from. Its value will affect the calculation of specifity for rules of this stylesheet.

Inline-styles will be handled on the fly, generating "mini-stylesheets" while walking the HTML parse tree. For `<style>`-elements, clients have to extract the styles in advance and wrap them into stylesheets.

func (CSSOM) RegisterCompoundSplitter

func (cssom CSSOM) RegisterCompoundSplitter(splitter CompoundPropertiesSplitter)

RegisterCompoundSplitter allows clients to handle additional compound properties. See type CompoundPropertiesSplitter.

func (CSSOM) Style

func (cssom CSSOM) Style(dom *html.Node, creator style.Creator) (*tree.Node, error)

Style gets things rolling. It styles an HTML parse tree, referred to by the root node, and returns a tree of styled nodes. For an explanation what's going on here, refer to https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/ and https://limpet.net/mbrubeck/2014/08/23/toy-layout-engine-4-style.html

If either dom or creator are nil, no tree is returned (but an error).

type CompoundPropertiesSplitter

type CompoundPropertiesSplitter func(string, style.Property) ([]style.KeyValue, error)

Compound properties are properties which abbreviate the setting of more fine grained propertes. An example is

padding: 10px 20px

which sets the following detail properties:

padding-top:    10px
padding-right:  20px
padding-bottom: 10px
padding-left:   20px

Standard CSS compound properties are known by default, but clients are allowed to extend the set of compound properties.

type PropertySource

type PropertySource uint8

Properties may be defined at different places in HTML: as a sytlesheet reference link, within a <script> element in the HTML file, or in an attribute value.

PropertySource affects the specifity of rules.

const (
	Global    PropertySource = iota + 1 // "browser" globals
	Author                              // CSS author (stylesheet link)
	Script                              // <script> element
	Attribute                           // in an element's attribute(s)
)

Values for property sources, used when adding style sheets.

type Rule

type Rule interface {
	Selector() string            // the prelude / selectors of the rule
	Properties() []string        // property keys, e.g. "margin-top"
	Value(string) style.Property // property value for key, e.g. "15px"
	IsImportant(string) bool     // is property key marked as important?
}

Rule is the type stylesheets consists of.

See interface StyleSheet.

type StyleSheet

type StyleSheet interface {
	AppendRules(StyleSheet) // append rules from another stylesheet
	Empty() bool            // does this stylesheet contain any rules?
	Rules() []Rule          // all the rules of a stylesheet
}

StyleSheet is an interface to abstract away a stylesheet-implementation. In order to de-couple implementations of CSS-stylesheets from the construction of the styled node tree, we introduce an interface for CSS stylesheets. Clients for the styling engine will have to provide a concrete implementation of this interface (e.g., see package douceuradapter).

Having this interface imposes a performance hit. However, this implementation of CSS-styling will never trade modularity and clarity for performance. Clients in need for a production grade browser engine (where performance is key) should opt for headless versions of the main browser projects.

See interface Rule.

Directories

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

Jump to

Keyboard shortcuts

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