Stylesheet¶
Path:
source/lexbor/css/stylesheet.h,source/lexbor/css/stylesheet.cIncludes:
lexbor/css/stylesheet.h
Overview¶
Stylesheet parsing converts a complete CSS text into a rule tree — the CSS Object Model (CSSOM). The result is a tree of lxb_css_rule_t nodes representing style rules, at-rules, and declarations.
Rule Tree Structure¶
A parsed stylesheet produces a tree of rules:
Stylesheet (lxb_css_rule_t, type = STYLESHEET)
+-- Rule List (lxb_css_rule_list_t)
|-- Style Rule (lxb_css_rule_style_t)
| |-- Selectors (lxb_css_selector_list_t)
| +-- Declaration List (lxb_css_rule_declaration_list_t)
| |-- Declaration (lxb_css_rule_declaration_t) /* e.g. color: red */
| +-- Declaration (lxb_css_rule_declaration_t) /* e.g. font-size: 16px */
|-- At-Rule (lxb_css_rule_at_t) /* e.g. @media */
| +-- Rule List (nested rules)
+-- Style Rule (lxb_css_rule_style_t)
+-- ...
Rule Types¶
Type |
Constant |
Description |
|---|---|---|
Stylesheet |
|
Root of the rule tree |
Rule List |
|
Container for rules (first/last) |
Style Rule |
|
Selector + declarations ( |
Bad Style Rule |
|
Malformed style rule (error recovery) |
At-Rule |
|
@-rule ( |
Declaration List |
|
List of declarations inside a rule |
Declaration |
|
Single property-value pair |
Structure¶
lxb_css_stylesheet_t¶
struct lxb_css_stylesheet {
lxb_css_rule_t *root; /* Root rule node */
lxb_css_memory_t *memory; /* Memory pool */
};
lxb_css_rule_t¶
Base rule type. All rule types embed this structure:
struct lxb_css_rule {
lxb_css_rule_type_t type; /* Rule type */
lxb_css_rule_t *next; /* Next sibling rule */
lxb_css_rule_t *prev; /* Previous sibling rule */
lxb_css_rule_t *parent; /* Parent rule */
lxb_css_memory_t *memory; /* Memory pool */
size_t ref_count;
};
lxb_css_rule_style_t¶
struct lxb_css_rule_style {
lxb_css_rule_t rule; /* Base rule */
lxb_css_selector_list_t *selector; /* Parsed selectors */
lxb_css_rule_declaration_list_t *declarations; /* Declarations */
lxb_css_rule_list_t *child; /* Nested rules */
};
lxb_css_rule_at_t¶
struct lxb_css_rule_at {
lxb_css_rule_t rule; /* Base rule */
uintptr_t type; /* At-rule type ID */
union {
lxb_css_at_rule__undef_t *undef;
lxb_css_at_rule__custom_t *custom;
lxb_css_at_rule_font_face_t *font_face;
lxb_css_at_rule_media_t *media;
lxb_css_at_rule_namespace_t *ns;
void *user;
} u;
};
API¶
lxb_css_stylesheet_create¶
lxb_css_stylesheet_t *
lxb_css_stylesheet_create(lxb_css_memory_t *memory);
Create a new stylesheet object. If memory is NULL, a new internal memory pool is created.
lxb_css_stylesheet_destroy¶
lxb_css_stylesheet_t *
lxb_css_stylesheet_destroy(lxb_css_stylesheet_t *sst, bool destroy_memory);
Destroy a stylesheet object. If destroy_memory is true, also destroys the attached memory pool.
lxb_css_stylesheet_parse¶
lxb_status_t
lxb_css_stylesheet_parse(lxb_css_stylesheet_t *sst, lxb_css_parser_t *parser,
const lxb_char_t *data, size_t length);
Parse CSS text and build the rule tree in the stylesheet.
Returns an error only in extremely unforeseen circumstances (e.g., memory allocation failure). Any broken CSS will not cause an error — it will be handled via error recovery.
If the parser does not have an initialized selectors module, one is created temporarily. For better performance when parsing multiple stylesheets, initialize selectors once:
lxb_css_parser_t *parser = lxb_css_parser_create();
lxb_css_parser_init(parser, NULL);
lxb_css_parser_selectors_init(parser);
Parsing Example¶
#include <lexbor/css/css.h>
int main(void)
{
const lxb_char_t css[] =
"div { color: red; }"
"@media (min-width: 768px) { .container { width: 100%; } }"
"p.intro { font-size: 18px; }";
/* Create parser */
lxb_css_parser_t *parser = lxb_css_parser_create();
lxb_css_parser_init(parser, NULL);
/* Create stylesheet (NULL = create its own memory pool) */
lxb_css_stylesheet_t *sst = lxb_css_stylesheet_create(NULL);
/* Parse CSS */
lxb_status_t status = lxb_css_stylesheet_parse(sst, parser, css,
sizeof(css) - 1);
if (status != LXB_STATUS_OK) {
/* Handle error */
}
/* The rule tree is now in sst->root */
/* Serialize, traverse, or inspect it... */
/* Clean up */
lxb_css_stylesheet_destroy(sst, true);
lxb_css_parser_destroy(parser, true);
return EXIT_SUCCESS;
}
Traversing the Rule Tree¶
Rules form a linked list. Each rule has next and prev pointers. A rule list has first and last pointers.
/* After parsing... */
lxb_css_rule_t *root = sst->root;
/* Root is a stylesheet rule with a child rule list */
/* Iterate through all top-level rules */
lxb_css_rule_list_t *list = lxb_css_rule_list(root);
lxb_css_rule_t *rule = list->first;
while (rule != NULL) {
switch (rule->type) {
case LXB_CSS_RULE_STYLE: {
lxb_css_rule_style_t *style = lxb_css_rule_style(rule);
/* Access style->selector and style->declarations */
break;
}
case LXB_CSS_RULE_AT_RULE: {
lxb_css_rule_at_t *at = lxb_css_rule_at(rule);
/* Access at-rule data */
break;
}
default:
break;
}
rule = rule->next;
}
Serialization¶
lxb_css_rule_serialize¶
lxb_status_t
lxb_css_rule_serialize(const lxb_css_rule_t *rule,
lexbor_serialize_cb_f cb, void *ctx);
Serialize a single rule node.
lxb_css_rule_serialize_chain¶
lxb_status_t
lxb_css_rule_serialize_chain(const lxb_css_rule_t *rule,
lexbor_serialize_cb_f cb, void *ctx);
Serialize a rule and all its siblings.
lxb_css_rule_list_serialize¶
lxb_status_t
lxb_css_rule_list_serialize(const lxb_css_rule_list_t *list,
lexbor_serialize_cb_f cb, void *ctx);
Serialize all rules in a rule list.
Cast Macros¶
Convenience macros for casting rule pointers:
Macro |
Target Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Reference Counting¶
Rules use reference counting for lifetime management:
Function |
Description |
|---|---|
|
Get current reference count |
|
Increment reference count |
|
Decrement reference count |
|
Decrement and destroy if count reaches 0 |