package cascade
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
CSS generation and manipulation library for OCaml
Install
dune-project
Dependency
Authors
Maintainers
Sources
cascade-1.2.1.tbz
sha256=1cf5079b3797cd6e70fbced8dc2631074f357d36fcdea8597c7ba17ac2903f6e
sha512=43f5e6a3986f8f43ce948b8f1d59f6f00e1047f5707c5449b6323b683d2ecd51a0fb34793aad9c48904a67b0f7268d7379ab9baf29917c25a962064bfa3ab694
doc/src/cascade/prune.ml.html
Source file prune.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128(* Remove the rules a set of documents cannot use. The matching is {!Resolve}; this decides what a No_match may be read as, which is the whole of the analysis: [Unsupported] is not a No_match, so a selector with no model is kept and never counted against the stylesheet. *) type verdict = Unused | Used of int | Unmodelled type entry = { selector : Selector.t; verdict : verdict } type analysis = { sheet : Stylesheet.t; entries : entry list; elements : int } module Make (Node : Resolve.NODE) = struct module R = Resolve.Make (Node) let rec collect acc node = List.fold_left collect (node :: acc) (Node.children node) let matched elements sel = List.fold_left (fun n e -> match R.match_selector sel e with | Resolve.Matches -> n + 1 | Resolve.No_match | Resolve.Unsupported -> n) 0 elements (* [supported] settles the question before any element is looked at, which is what keeps [Unused] a statement about the documents: were the count taken first, a selector the matcher cannot decide would come back at zero and read as ruled out. *) let judge elements (r : Stylesheet.rule) = match r.nested with | _ :: _ -> Unmodelled | [] -> ( if not (Resolve.supported r.selector) then Unmodelled else match matched elements r.selector with 0 -> Unused | n -> Used n) (* Selectors 4 sec. 3.3: a selector list is a set of selectors, each matching on its own and carrying its own specificity (sec. 17), so a branch nothing matches goes while the rest of the rule stays. A list is supported only when every branch is, so every branch reached here is modelled. *) let live_branches elements sel = match Selector.as_list sel with | None -> None | Some branches -> ( match List.filter (fun b -> matched elements b > 0) branches with | kept when List.compare_lengths kept branches = 0 -> None | [] -> None | [ one ] -> Some one | kept -> Some (Selector.list kept)) let rec block elements acc stmts = let acc, out = List.fold_left (fun (acc, out) stmt -> match statement elements acc stmt with | acc, None -> (acc, out) | acc, Some s -> (acc, s :: out)) (acc, []) stmts in (acc, List.rev out) and statement elements acc stmt = (* A group block left with nothing goes with its rules: the condition it carries guards no declaration any more. [@layer] is the exception, since an empty one still declares a layer the cascade orders by (css-cascade-5 sec. 6.4.4). *) let group acc body rebuild = let acc, pruned = block elements acc body in match (body, pruned) with | _ :: _, [] -> (acc, None) | _ -> (acc, Some (rebuild pruned)) in match stmt with | Stylesheet.Rule r -> let selector = r.selector in let verdict = judge elements r in let acc = { selector; verdict } :: acc in let kept = match verdict with | Unused -> None | Unmodelled -> Some stmt | Used _ -> ( match live_branches elements selector with | None -> Some stmt | Some selector -> Some (Stylesheet.Rule { r with selector })) in (acc, kept) | Stylesheet.Layer (name, body) -> let acc, pruned = block elements acc body in (acc, Some (Stylesheet.Layer (name, pruned))) | Stylesheet.Media (query, body) -> group acc body (fun b -> Stylesheet.Media (query, b)) | Stylesheet.Supports (cond, body) -> group acc body (fun b -> Stylesheet.Supports (cond, b)) | Stylesheet.Container (name, cond, body) -> group acc body (fun b -> Stylesheet.Container (name, cond, b)) | Stylesheet.Moz_document (conds, body) -> group acc body (fun b -> Stylesheet.Moz_document (conds, b)) | Stylesheet.Starting_style body -> group acc body (fun b -> Stylesheet.Starting_style b) | Stylesheet.When (cond, body) -> group acc body (fun b -> Stylesheet.When (cond, b)) | Stylesheet.Else (cond, body) -> group acc body (fun b -> Stylesheet.Else (cond, b)) | Stylesheet.Scope (root, limit, body) -> (* The scoping root is not judged: css-cascade-6 puts the elements in scope behind a proximity criterion the matcher does not model, so a root that matches nothing here says nothing about the rules inside. *) group acc body (fun b -> Stylesheet.Scope (root, limit, b)) | Stylesheet.Origin (origin, body) -> group acc body (fun b -> Stylesheet.Origin (origin, b)) (* Nothing here names an element, so no document can rule it out. *) | Stylesheet.Declarations _ | Stylesheet.Bang_comment _ | Stylesheet.Charset _ | Stylesheet.Import _ | Stylesheet.Namespace _ | Stylesheet.Property _ | Stylesheet.Layer_decl _ | Stylesheet.Supports_condition _ | Stylesheet.Keyframes _ | Stylesheet.Webkit_keyframes _ | Stylesheet.Moz_keyframes _ | Stylesheet.Font_face _ | Stylesheet.Counter_style _ | Stylesheet.Page _ | Stylesheet.Page_with_margins _ | Stylesheet.Font_palette_values _ | Stylesheet.Font_feature_values _ | Stylesheet.View_transition _ | Stylesheet.Position_try _ | Stylesheet.Viewport _ | Stylesheet.Unknown_at_rule _ -> (acc, Some stmt) let analyse ~sheet roots = let elements = List.fold_left collect [] roots in let entries, sheet = block elements [] (Flatten.block sheet) in { sheet; entries = List.rev entries; elements = List.length elements } end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>