module Asciidoctor::Substitutors

def parse_quoted_text_attributes str

Returns a Hash of attributes (role and id only)

space-separated roles (e.g., role1 role2) or the id/role shorthand syntax (e.g., #idname.role)
str - A non-nil String of unprocessed attributes;

Internal: Parse the attributes that are defined on quoted (aka formatted) text
def parse_quoted_text_attributes str
  # NOTE attributes are typically resolved after quoted text, so substitute eagerly
  str = sub_attributes str if str.include? ATTR_REF_HEAD
  # for compliance, only consider first positional attribute (very unlikely)
  str = str.slice 0, (str.index ',') if str.include? ','
  if (str = str.strip).empty?
    {}
  elsif (str.start_with? '.', '#') && Compliance.shorthand_property_syntax
    before, _, after = str.partition '#'
    attrs = {}
    if after.empty?
      attrs['role'] = (before.tr '.', ' ').lstrip if before.length > 1
    else
      id, _, roles = after.partition '.'
      attrs['id'] = id unless id.empty?
      if roles.empty?
        attrs['role'] = (before.tr '.', ' ').lstrip if before.length > 1
      elsif before.length > 1
        attrs['role'] = ((before + '.' + roles).tr '.', ' ').lstrip
      else
        attrs['role'] = roles.tr '.', ' '
      end
    end
    attrs
  else
    { 'role' => str }
  end
end