| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- open Types
- (* This file defines functions that construct an element tree with applied
- * stylesheet based on:
- * - http://www.w3.org/TR/CSS2/cascade.html#specificity
- *)
- let is_pseudo_class = function
- | Pseudo_class (_, ("link" | "hover" | "visited" | "active"), None) -> true
- | _ -> false
- (* Specificity (a, b, c, d):
- * a = 0 (1 if in style="" definition which is always false in a stylesheet)
- * b = number of ID attributes
- * c = number of other (pseudo-)attributes
- * d = number of (pseudo-)elements
- *)
- let rec specificity =
- let add (a, b, c, d) (e, f, g, h) = (a + e, b + f, c + g, d + h) in
- function
- | No_element | All_elements ->
- (0, 0, 0, 0)
- | Element _ ->
- (0, 0, 0, 1)
- | Id (base, _) ->
- add (0, 1, 0, 0) (specificity base)
- | Class (base, _) | Attribute (base, _, _) ->
- add (0, 0, 1, 0) (specificity base)
- | Pseudo_class (base, _, _) as addon when is_pseudo_class addon ->
- add (0, 0, 1, 0) (specificity base)
- | Pseudo_class (base, _, _) ->
- add (0, 0, 0, 1) (specificity base)
- (* XXX: Pseudo_element *)
- | Combinator (left, _, right) ->
- add (specificity left) (specificity right)
- let precedes (a, b, c, d) (e, f, g, h) =
- let rec loop = function
- | [] -> true
- | 0 :: tl -> loop tl
- | n :: _ when n > 0 -> true
- | _ -> false
- in
- loop [a - e; b - f; c - g; d - h]
- let overwrites selector1 selector2 =
- precedes (specificity selector1) (specificity selector2)
- let can_match_same selector1 selector2 =
- let unfold =
- let rec loop classes ids pseudos attrs = function
- | No_element ->
- ("", classes, ids, pseudos, attrs)
- | All_elements ->
- ("*", classes, ids, pseudos, attrs)
- | Element elem ->
- (elem, classes, ids, pseudos, attrs)
- | Id (base, id) ->
- loop classes (id :: ids) pseudos attrs base
- | Class (base, cls) ->
- loop (cls :: classes) ids pseudos attrs base
- | Pseudo (base, f, arg) ->
- (* XXX: what about :not(...) ? *)
- loop classes ids ((f, arg) :: pseudos) attrs base
- | Attribute (base, attr, _) ->
- loop classes ids pseudos (attr :: attrs) base
- | Combinator (_, _, right) ->
- loop classes ids pseudos attrs right
- in
- loop [] [] [] []
- in
- let rec intersect l = function
- | [] -> false
- | hd :: _ when List.mem hd l -> true
- | _ :: tl -> intersect l tl
- in
- let elem1, classes1, ids1, pseudos1, attrs1 = unfold selector1 in
- let elem2, classes2, ids2, pseudos2, attrs2 = unfold selector2 in
- elem1 = "*" || elem2 = "*" || elem1 = elem2 && elem1 <> "" ||
- intersect classes1 classes2 ||
- intersect ids1 ids2 ||
- intersect pseudos1 pseudos2 ||
- intersect attrs1 attrs2
|