module ComponentFactory def component_factory(elem) inner = elem.children.map(&:to_s).join # TODO: Handle changed names transform_method = :"_transform_#{self.component_lookup[elem.name]}" if self.respond_to?(transform_method) REXML::Document.new(self.send(transform_method, elem, inner)).root else nil end end def _pass_through_attributes(elem) ignored = ['class', 'id', 'href', 'size', 'large', 'no-expander', 'small', 'target']; elem.attributes.map do |name, value| if ignored.include?(name.downcase) '' else "#{name}=\"#{value}\"" end end.join(' ') end def _has_class(elem, klass) !!elem.attributes['class'] && elem.attributes['class'].split(' ').include?(klass) end def _class_array(elem, defaults = []) (elem.attributes['class'] ? (defaults.concat(elem.attributes['class'].split(' '))) : defaults).uniq end def _target_attribute(elem) elem.attributes['target'] ? " target=\"#{elem.attributes['target']}\"" : '' end def _transform_button(component, inner) expand = _has_class(component, 'expand') if component.attributes['href'] target = _target_attribute(component) if expand inner = "#{inner}" else inner = "#{inner}" end end inner = "
#{inner}
" if expand classes = _class_array(component, ['button']) if expand return "
#{inner}
" else return "
#{inner}
" end end def _transform_menu(component, inner) classes = _class_array(component, ['menu']) "
#{inner}
" end def _transform_menu_item(component, inner) target = _target_attribute(component) "#{inner}" end def _transform_container(component, inner) classes = _class_array(component, ['container']) "
#{inner}
" end def _transform_row(component, inner) classes = _class_array(component, ['row']) attrs = _pass_through_attributes(component) "#{inner}
" end # in inky.js this is factored out into makeClumn. TBD if we need that here. def _transform_columns(component, inner) col_count = component.parent.elements.size small_size = component.attributes['small'] || self.column_count large_size = component.attributes['large'] || component.attributes['small'] || (self.column_count / col_count).to_i classes = _class_array(component, ["small-#{small_size}", "large-#{large_size}", "columns"]) classes.push('first') unless component.previous_element classes.push('last') unless component.next_element subrows = component.elements.to_a("//*[contains(@class,'row')]").concat(component.elements.to_a("//row")) expander = '' if large_size.to_i == self.column_count && subrows.size == 0 expander = "" end "#{expander}
#{inner}
" end def _transform_block_grid(component, inner) classes = _class_array(component, ['block-grid', "up-#{component.attributes['up']}"]) "#{inner}
" end def _transform_center(component, inner) # NOTE: Using children instead of elements because elements.to_a # sometimes appears to miss elements that show up in size component.elements.to_a.each do |child| child.add_attribute('align', 'center') child_classes = _class_array(child, ['float-center']) child.add_attribute('class', child_classes.join(' ')) items = component.elements.to_a("//*[contains(@class,'menu-item')]").concat(component.elements.to_a("//item")) items.each do |item| item_classes = _class_array(item, ['float-center']) item.add_attribute('class', item_classes.join(' ')) end end return component.to_s end def _transform_callout(component, inner) classes = _class_array(component, ['callout-inner']) return "
#{inner}
" end def _transform_spacer(component, inner) classes = _class_array(component, ['spacer']) size = component.attributes['size'] size_sm = component.attributes['size-sm'] size_lg = component.attributes['size-lg'] if size_sm || size_lg html = '' if size_sm html += "
 
" end if size_lg html += "
 
" end if size_sm && size_lg # REXML doesn't like replacing a single element with a double html = "#{html}" end return html else size ||= 16 return "
 
" end end def _transform_wrapper(component, inner) classes = _class_array(component, ['wrapper']) return "
#{inner}
" end end