1
# frozen_string_literal: true
2

3 5
require 'forwardable'
4

5 5
module Roadie
6
  # @api private
7
  # A style block is the combination of a {Selector} and a list of {StyleProperty}.
8 5
  class StyleBlock
9 5
    extend Forwardable
10 5
    attr_reader :selector, :properties, :media
11

12
    # @param [Selector] selector
13
    # @param [Array<StyleProperty>] properties
14
    # @param [Array<String>] media  Array of media types, e.g.
15
    #                          @media screen, print and (max-width 800px) will become
16
    #                          ['screen', 'print and (max-width 800px)']
17 5
    def initialize(selector, properties, media)
18 5
      @selector = selector
19 5
      @properties = properties
20 5
      @media = media.map(&:to_s)
21
    end
22

23
    # @!method specificity
24
    #   @see Selector#specificity
25 5
    def_delegators :selector, :specificity
26
    # @!method selector_string
27
    #   @see Selector#to_s
28 5
    def_delegator :selector, :to_s, :selector_string
29

30
    # Checks whether the media query can be inlined
31
    # @see inlineable_media
32
    # @return {Boolean}
33 5
    def inlinable?
34 5
      inlinable_media? && selector.inlinable?
35
    end
36

37
    # String representation of the style block. This is valid CSS and can be
38
    # used in the DOM.
39
    # @return {String}
40 5
    def to_s
41
      # NB - leave off redundant final semicolon - see https://www.w3.org/TR/CSS2/syndata.html#declaration
42 5
      "#{selector}{#{properties.map(&:to_s).join(';')}}"
43
    end
44

45 5
    private
46

47
    # A media query cannot be inlined if it contains any advanced rules
48
    # e.g. @media only screen {...} is ok to inline but
49
    # @media only screen and (max-width: 600px) {...} cannot be inlined
50
    # @return {Boolean}
51 5
    def inlinable_media?
52 5
      @media.none? { |media_query| media_query.include? '(' }
53
    end
54
  end
55
end

Read our documentation on viewing source code .

Loading