# File lib/asciidoctor/parser.rb, line 2522
  def self.parse_style_attribute(attributes, reader = nil)
    # NOTE spaces are not allowed in shorthand, so if we detect one, this ain't no shorthand
    if (raw_style = attributes[1]) && !raw_style.include?(' ') && Compliance.shorthand_property_syntax
      type, collector, parsed = :style, [], {}
      # QUESTION should this be a private method? (though, it's never called if shorthand isn't used)
      save_current = lambda {
        if collector.empty?
          unless type == :style
            warn %(asciidoctor: WARNING:#{reader ? " #{reader.prev_line_info}:" : nil} invalid empty #{type} detected in style attribute)
          end
        else
          case type
          when :role, :option
            (parsed[type] ||= []) << collector.join
          when :id
            if parsed.key? :id
              warn %(asciidoctor: WARNING:#{reader ? " #{reader.prev_line_info}:" : nil} multiple ids detected in style attribute)
            end
            parsed[type] = collector.join
          else
            parsed[type] = collector.join
          end
          collector = []
        end
      }

      raw_style.each_char do |c|
        if c == '.' || c == '#' || c == '%'
          save_current.call
          case c
          when '.'
            type = :role
          when '#'
            type = :id
          when '%'
            type = :option
          end
        else
          collector << c
        end
      end

      # small optimization if no shorthand is found
      if type == :style
        attributes['style'] = raw_style
      else
        save_current.call

        parsed_style = attributes['style'] = parsed[:style] if parsed.key? :style

        attributes['id'] = parsed[:id] if parsed.key? :id

        attributes['role'] = parsed[:role] * ' ' if parsed.key? :role

        if parsed.key? :option
          (options = parsed[:option]).each {|option| attributes[%(#{option}-option)] = '' }
          if (existing_opts = attributes['options'])
            attributes['options'] = (options + existing_opts.split(',')) * ','
          else
            attributes['options'] = options * ','
          end
        end

        parsed_style
      end
    else
      attributes['style'] = raw_style
    end
  end