Class: Cataract::Backends::PureImpl Private
- Inherits:
-
Object
- Object
- Cataract::Backends::PureImpl
- Defined in:
- lib/cataract/pure.rb,
lib/cataract/pure/parser.rb,
lib/cataract/pure/flatten.rb,
lib/cataract/pure/serializer.rb,
lib/cataract/pure/specificity.rb,
lib/cataract/pure/declarations.rb,
lib/cataract/pure/byte_constants.rb
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Defined Under Namespace
Classes: FlattenImpl, Parser, Serializer
Constant Summary collapse
- PURE_RUBY_LOADED =
Flag to indicate the pure Ruby backend is loaded
true- IMPLEMENTATION =
Implementation type constant
:ruby- COMPILE_FLAGS =
Compile flags (mimic C version)
{ debug: false, str_buf_optimization: false, pure_ruby: true }.freeze
- Flatten =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
A frozen singleton, same rationale as Pure itself (see pure.rb) - none of FlattenImpl's methods touch instance state, so one shared instance is as safe as the bare module this replaces.
FlattenImpl.new.freeze
- PSEUDO_ELEMENT_KEYWORDS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Legacy CSS2 pseudo-elements written with a single colon (e.g. :before) that must still be counted as pseudo-elements, not pseudo-classes.
%w[before after first-line first-letter selection].freeze
- BYTE_SPACE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Whitespace bytes
32- BYTE_TAB =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
' '
9- BYTE_NEWLINE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'\t'
10- BYTE_CR =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'\n'
13- BYTE_AT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
CSS structural characters
64- BYTE_LBRACE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'@'
123- BYTE_RBRACE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'{'
125- BYTE_LPAREN =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'}'
40- BYTE_RPAREN =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'('
41- BYTE_LBRACKET =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
')'
91- BYTE_RBRACKET =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'['
93- BYTE_SEMICOLON =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
']'
59- BYTE_COLON =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
';'
58- BYTE_COMMA =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
':'
44- BYTE_SLASH =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Comment characters
47- BYTE_STAR =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'/'
42- BYTE_SQUOTE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Quote characters
39- BYTE_DQUOTE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
"'"
34- BYTE_HASH =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Selector characters
35- BYTE_DOT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'#'
46- BYTE_GT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'.'
62- BYTE_PLUS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'>'
43- BYTE_TILDE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'+'
126- BYTE_ASTERISK =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'~'
42- BYTE_AMPERSAND =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'*'
38- BYTE_HYPHEN =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Other
45- BYTE_UNDERSCORE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'-'
95- BYTE_BACKSLASH =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'_'
92- BYTE_BANG =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'\'
33- BYTE_PERCENT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'!'
37- BYTE_EQUALS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'%'
61- BYTE_CARET =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'='
94- BYTE_DOLLAR =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'^'
36- BYTE_PIPE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'$'
124- BYTE_LOWER_U =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Specific lowercase letters (for keyword matching)
117- BYTE_LOWER_R =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'u'
114- BYTE_LOWER_L =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'r'
108- BYTE_LOWER_D =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'l'
100- BYTE_LOWER_T =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'd'
116- BYTE_LOWER_N =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
't'
110- BYTE_UPPER_U =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Specific uppercase letters (for case-insensitive matching)
85- BYTE_UPPER_R =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'U'
82- BYTE_UPPER_L =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'R'
76- BYTE_UPPER_D =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'L'
68- BYTE_UPPER_T =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'D'
84- BYTE_UPPER_N =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'T'
78- BYTE_LOWER_A =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Letter ranges (a-z, A-Z)
97- BYTE_LOWER_Z =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'a'
122- BYTE_UPPER_A =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'z'
65- BYTE_UPPER_Z =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'A'
90- BYTE_CASE_DIFF =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'Z'
32- BYTE_DIGIT_0 =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Digit range (0-9)
48- BYTE_DIGIT_9 =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'0'
57- NESTING_STYLE_IMPLICIT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Nesting styles (for CSS nesting support)
0- NESTING_STYLE_EXPLICIT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Implicit nesting: .parent { .child { ... } } => .parent .child
1
Instance Method Summary collapse
-
#calculate_specificity(selector) ⇒ Integer
private
Calculate CSS specificity for a selector.
-
#expand_shorthand(decl) ⇒ Array<Declaration>
Expand a single shorthand declaration into longhand declarations.
-
#flatten(stylesheet) ⇒ Stylesheet
Flatten stylesheet rules according to CSS cascade rules.
-
#parse(css_string, parser_options = {}) ⇒ Hash
Parse CSS string and return hash with rules, media_index, charset, etc.
-
#parse_declarations(str) ⇒ Array<Declaration>
private
Parse a standalone CSS declaration-list string ("color: red; margin: 10px") into an array of Declaration structs.
-
#stylesheet_to_formatted_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) ⇒ String
private
Serialize stylesheet to formatted CSS string (with indentation).
-
#stylesheet_to_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) ⇒ String
private
Serialize stylesheet to compact CSS string.
Instance Method Details
#calculate_specificity(selector) ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Calculate CSS specificity for a selector
Specificity calculation (per CSS spec):
- Count IDs (#id) - each worth 100
- Count classes/attributes/pseudo-classes (.class, [attr], :pseudo) - each worth 10
- Count elements/pseudo-elements (div, ::before) - each worth 1
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 |
# File 'lib/cataract/pure/specificity.rb', line 39 def calculate_specificity(selector) return 0 if selector.nil? || selector.empty? # Counters for specificity components id_count = 0 class_count = 0 attr_count = 0 pseudo_class_count = 0 pseudo_element_count = 0 element_count = 0 i = 0 len = selector.length while i < len byte = selector.getbyte(i) if byte == BYTE_HASH id_count += 1 i = skip_identifier(selector, i + 1, len) elsif byte == BYTE_DOT class_count += 1 i = skip_identifier(selector, i + 1, len) elsif byte == BYTE_LBRACKET attr_count += 1 i = skip_attribute_selector(selector, i, len) elsif byte == BYTE_COLON i, is_not, not_content, counts_as_element = parse_pseudo(selector, i, len) if not_content # :not() doesn't count itself, but its content does not_specificity = calculate_specificity(not_content) id_count += not_specificity / 100 class_count += (not_specificity % 100) / 10 element_count += not_specificity % 10 elsif !is_not if counts_as_element pseudo_element_count += 1 else pseudo_class_count += 1 end end elsif letter?(byte) element_count += 1 i = skip_identifier(selector, i + 1, len) else # Whitespace, combinators, and the universal selector (*) all have # zero specificity - just skip a single byte. i += 1 end end # Calculate specificity using W3C formula (id_count * 100) + ((class_count + attr_count + pseudo_class_count) * 10) + ((element_count + pseudo_element_count) * 1) end |
#expand_shorthand(decl) ⇒ Array<Declaration>
Expand a single shorthand declaration into longhand declarations. Called by Rule#expanded_declarations - not meant for direct use.
100 101 102 |
# File 'lib/cataract/pure.rb', line 100 def (decl) Flatten.(decl) end |
#flatten(stylesheet) ⇒ Stylesheet
Flatten stylesheet rules according to CSS cascade rules
91 92 93 |
# File 'lib/cataract/pure.rb', line 91 def flatten(stylesheet) Flatten.flatten(stylesheet, mutate: false) end |
#parse(css_string, parser_options = {}) ⇒ Hash
Parse CSS string and return hash with rules, media_index, charset, etc. Called by Stylesheet#add_block - not meant for direct use.
}
82 83 84 85 |
# File 'lib/cataract/pure.rb', line 82 def parse(css_string, = {}) parser = Parser.new(css_string, parser_options: ) parser.parse end |
#parse_declarations(str) ⇒ Array<Declaration>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parse a standalone CSS declaration-list string ("color: red; margin: 10px") into an array of Declaration structs.
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 |
# File 'lib/cataract/pure/declarations.rb', line 24 def parse_declarations(str) fin = str.bytesize pos = 0 # Strip outer braces and whitespace (css_parser compatibility) pos += 1 while pos < fin && (decl_whitespace?(str.getbyte(pos)) || str.getbyte(pos) == BYTE_LBRACE) fin -= 1 while fin > pos && (decl_whitespace?(str.getbyte(fin - 1)) || str.getbyte(fin - 1) == BYTE_RBRACE) declarations = [] while pos < fin pos += 1 while pos < fin && (decl_whitespace?(str.getbyte(pos)) || str.getbyte(pos) == BYTE_SEMICOLON) break if pos >= fin span = scan_one_declaration(str, pos, fin) break unless span # No colon found - stop parsing entirely pos = span[:next_pos] next unless span[:val_end] > span[:val_start] # Skip if value is empty property = str.byteslice(span[:prop_start], span[:prop_end] - span[:prop_start]) .force_encoding(Encoding::US_ASCII).downcase value = str.byteslice(span[:val_start], span[:val_end] - span[:val_start]).force_encoding(Encoding::UTF_8) declarations << Declaration.new(property, value, span[:important]) end declarations end |
#stylesheet_to_formatted_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Serialize stylesheet to formatted CSS string (with indentation).
654 655 656 657 658 |
# File 'lib/cataract/pure/serializer.rb', line 654 def stylesheet_to_formatted_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) Serializer.new(rules, charset, has_nesting, selector_lists, media_queries, media_query_lists, formatted: true).to_s end |
#stylesheet_to_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Serialize stylesheet to compact CSS string.
641 642 643 |
# File 'lib/cataract/pure/serializer.rb', line 641 def stylesheet_to_s(rules, charset, has_nesting, selector_lists = {}, media_queries = [], media_query_lists = {}) Serializer.new(rules, charset, has_nesting, selector_lists, media_queries, media_query_lists, formatted: false).to_s end |