grafthistory: support curl
[elinks/elinks-j605.git] / src / document / css / README
blobcc7564ccf000d7cb8ff6c8a3e9a29095c055b3ad
1 This is a super-simplistic CSS micro-engine.
3                                     Phases
5 The CSS handling is divided into:
7 * The scanner
9 It takes care of composing tokens from a string containing CSS source. It
10 also takes care of eliminating either garbage code that was not recognized
11 or things like whitespace and comments. The scanner will not attempt to
12 recover from this garbage code but merely signal them to the upper layers.
14 The scanner only works with strings but is a bit more high level than
15 scanners in the sense of flex. The string "10em" will not just generate the
16 two tokens <number>, <identifier> but rather combine them into one token.
17 This only leads to problems with tokens of the sort #<identifier> that can
18 be both a hex color or hash so should not be a problem but rather mean that
19 we will do less scanner calls.
21 The scanner lives in scanner.*
23 * The parser
25 It takes a string with CSS code, composes tokens (from the scanner) into
26 some meaningful syntax and transforms it to an internal set of structures
27 describing the data (let's call it a "rawer"). It currently does no recovery
28 when something unexpected shows up but skips to next special control char.
30 The parser lives in parser.* and value.*
32 * The applier
34 It applies style info from a syntax tree (parsed ELinks or document
35 stylesheet) or fragment of one (in the case of style="" attributes) to the
36 current element.
38 The applier lives in apply.*
41                               The current state
43 Currently we both check the element's 'style' attribute, content of <style>
44 tags and imports from either <link> tags in the HTML header or @imports from
45 the CSS code. But we lack a proper way to handle the cascading. Now it will
46 automatically scan the current element, and if a 'style' attribute is found,
47 it is parsed and applied to the current element.  If there is no 'style'
48 attribute it will look up any styles retrieved from the document stylesheet
49 and last try styles from the default user controlled stylesheet. TODO: We
50 should always look up <style> tags and only apply those not found in any
51 'style' attribute.
53 One big problem with the current way of doing things is inheritance, there
54 is no way we are telling the HTML engine what is going to be inherited and
55 what is not. The other problem is precedence, currently even global
56 stylesheet takes precedence over local classic-formatting attributes (we
57 just css_apply() like mad on various places to make sure the CSS attributes
58 are stuffed through HTML engine's throat). These two problems will be solved
59 when the HTML engine is converted to work with stylesheets natively (instead
60 of format + par_format).
63                                The selectors tree
65 In order to handle any non-trivial selectors, we need them to form a certain
66 structure. A hierarchical one was chosen, where we initially focus on a
67 the most specific element, then we build the way down through ids, classes
68 and pseudo-classes and then back the way up through parent elements.
70 Assume two statements: "div#foo p a>b i:baz { color: black; }" and
71 "div#foo.bar p a>b i:baz { text-decoration: underline; }". The tree we build up
72 is:
74                 element[i]
75                 | (pseudo_classes)
76                 pseudo_class[baz]
77                 | (ancestors)
78                 element[b]
79                 | (parents)
80                 element[a]
81                 | (ancestors)
82                 element[p]
83                 | (ancestors)
84                 element[div]
85                 | (ids)
86                 id[foo] -> (color: black)
87                 | (classes)
88                 class[bar] -> (text-decoration: underline)
90 As you can see, the combinators hierarchy is reverse, while the other selectors
91 hierarchy is as usual. This is to aid the applier, it goes from the general to
92 the specific (that's how it is from the POV of applying stuff to single
93 elements, even though the ancestors are more "general" from the POV of the
94 document stucture). This approach has its deficiencies as well (it can be
95 expensive to match long complex combinators since we need to walk through the
96 ancestry each time we match an element, or even more frequently when we
97 consider the element with varied specificities ("i", "i#x", "i:baz",
98 "i#x:baz")) but it still looks like the best way (because of the varied
99 specificities, you can't well go the other way by narrowing down the selectors
100 as you descend the elements tree).
102 Let's close the discourse by adding another two selectors to the stylesheet:
103 "b i#x:baz { color: blue; }" and "a>b#foo i:baz { background: white; }".
105                 element[i] -------------.
106                 | (pseudo_classes)      | (ids)
107                 pseudo_class[baz]       id[x]
108                 | (ancestors)           | (pseudo_classes)
109   .------------ element[b]              pseudo_class[baz]
110   | (ids)       | (parents)             | (ancestors)
111   id[foo]       element[a]              element[b] -> (color: blue)
112   | (parents)   | (ancestors)
113   element[a]    element[p]
114    -> (b: w)    | (ancestors)
115                 element[div]
116                 | (ids)
117                 id[foo] -> (color: black)
118                 | (classes)
119                 class[bar] -> (text-decoration: underline)
121 As you can see a tiny alternation of specificity at the top of the tree will
122 duplicate the whole path of combinators, but you can't get away without that,
123 I think.
125 You can get probably a much better overview of how it looks by #define
126 DEBUG_CSS at the top of src/document/css/stylesheet.h, recompiling and then
127 grabbing a dumped stylesheet tree from stderr. Translate the 'type' and 'rel'
128 fields from numbers to actual values accordingly to the enums in the
129 aforementioned header file.
132                             The future of selectors
134 XXX: I keep this here only for a historical reference now. The order matters,
135 the connecting lines probably not. --pasky
137 Specificity
139 111             a#id.nav
140 .                   |
141 .               .---'---.
142 .               V       |
143 101            a#id     |
144 .               |       |
145 .               |       |
146 .               |       |
147 13              |       |                      div p a.nav
148 .               |       |                           |
149 .               |       |           .--------------'|
150 .               |       |           V               |
151 12              |       |        p a.nav            |
152 .               |       |           |               |
153 .               |       `-.---------'               |
154 .               |         V                         |
155 11              |       a.nav                       |
156 .               |         |                         |
157 .               |         |                         |
158 .               |         |                         |
159 2               |         |    p a                  |
160 .               |         |     |                   |
161 .               `---------`-.---'---.               |
162 .                           V       V               |
163 1                           a       p      img     div
164 .                           |         |     |       |
165 .                           `-------+---+---+-------'
166 .                                       V
167 0                                       * (universal selector)