def initialize_css_style_conversion
      @defined_style_conversions = {
        # styles shared or common logic across all node types go here.
        # Special conversion lambdas such as :_border can be
        # defined here for reuse across several AST nodes. Care must
        # be taken to avoid possible naming conflicts, hence the underscore.
        # AST class keys should be stored with their names converted from
        # camelcase to lowercased snakecase, i.e. TestCase = test_case
        node: {
          'background-color' => lambda { |v|
            return 'shd', { val: 'clear', fill: v.delete('#') }
          },
          _border: lambda { |v|
            props = { sz: 2, val: 'single', color: '000000' }
            vals = v.split
            vals[1] = 'single' if vals[1] == 'solid'
            #
            props[:sz] = @defined_style_conversions[:node][:_sz].call(vals[0])
            props[:val] = vals[1] if vals[1]
            props[:color] = vals[2].delete('#') if vals[2]
            #
            return props
          },
          _sz: lambda { |v|
            return nil unless v
            (2 * Float(v.gsub(/[^\d.]/, '')).ceil).to_s
          },
          'text-align' => ->(v) { return 'jc', v }
        },
        # Styles specific to the Table AST class
        table: {
          'border' => lambda { |v|
            props = @defined_style_conversions[:node][:_border].call(v)
            #
            return 'tblBorders', [
              { top: props }, { start: props }, { bottom: props },
              { end: props }, { insideH: props }, { insideV: props }
            ]
          },
          'margin' => lambda { |v|
            vals = v.split.map do |s|
              @defined_style_conversions[:node][:_sz].call(s)
            end
            #
            props = [vals[0], vals[0], vals[0], vals[0]] if vals.length == 1
            props = [vals[0], vals[1], vals[0], vals[1]] if vals.length == 2
            props = [vals[0], vals[1], vals[2], vals[1]] if vals.length == 3
            props = [vals[0], vals[1], vals[2], vals[3]] if vals.length > 3
            return 'tblCellMar', [
              { top: { w: props[0], type: 'dxa' } },
              { end: { w: props[1], type: 'dxa' } },
              { bottom: { w: props[2], type: 'dxa' } },
              { start: { w: props[3], type: 'dxa' } }
            ]
          },
          'cellspacing' => lambda { |v|
            v = @defined_style_conversions[:node][:_sz].call(v)
            return 'tblCellSpacing', { w: v, type: 'dxa' }
          },
          'width' => lambda { |v|
            v = @defined_style_conversions[:node][:_sz].call(v)
            return 'tblW', { w: v, type: 'dxa' }
          }
        },
        # Styles specific to the TableCell AST class
        table_cell: {
          'border' => lambda { |v|
            value = @defined_style_conversions[:table]['border'].call(v)[1]
            return 'tcBorders', value
          },
          'colspan' => ->(v) { return 'gridSpan', v },
          'margin' => lambda { |v|
            value = @defined_style_conversions[:table]['margin'].call(v)[1]
            return 'tcMar', value
          },
          'rowspan' => lambda { |v|
            return 'vMerge', 'restart' if v == 'start'
            return 'vMerge', v if v == 'continue'
            return 'vMerge', nil if v == 'end'
          },
          'vertical-align' => ->(v) { return 'vAlign', v },
          'white-space' => lambda { |v|
            return 'noWrap', nil if v == 'nowrap'
            return 'tcFitText', 'true' if v == 'fit'
          },
          'width' => lambda { |v|
            value = @defined_style_conversions[:table]['width'].call(v)[1]
            return 'tcW', value
          }
        },
        # Styles specific to the Paragraph AST class
        paragraph: {
          'border' => lambda { |v|
            props = @defined_style_conversions[:node][:_border].call(v)
            #
            return 'pBdr', [
              { top: props }, { bottom: props },
              { left: props }, { right: props }
            ]
          },
          'vertical-align' => ->(v) { return 'textAlignment', v }
        },
        # Styles specific to a run of text
        run: {
          'color' => ->(v) { return 'color', v.delete('#') },
          'font-size' => lambda { |v|
            return 'sz', @defined_style_conversions[:node][:_sz].call(v)
          },
          'font-style' => lambda { |v|
            return 'b', nil if v =~ /bold/
            return 'i', nil if v =~ /italic/
          },
          'font-weight' => ->(v) { return 'b', nil if v =~ /bold/ },
          'text-decoration' => lambda { |v|
            supported = %w[line-through underline]
            props = v.split
            return props[0], 'true' unless supported.include? props[0]
            return 'strike', 'true' if props[0] == 'line-through'
            return 'u', 'single' if props.length == 1
            return 'u', { val: props[1], color: 'auto' } if props.length == 2
            return 'u', { val: props[1], color: props[2].delete('#') }
          },
          'vertical-align' => lambda { |v|
            return 'vertAlign', 'subscript' if v =~ /sub/
            return 'vertAlign', 'superscript' if v =~ /super/
          }
        }
      }
    end
def initialize_css_style_conversion
      @defined_style_conversions = {
        # styles shared or common logic across all node types go here.
        # Special conversion lambdas such as :_border can be
        # defined here for reuse across several AST nodes. Care must
        # be taken to avoid possible naming conflicts, hence the underscore.
        # AST class keys should be stored with their names converted from
        # camelcase to lowercased snakecase, i.e. TestCase = test_case
        node: {
          'background-color' => lambda { |v|
            return 'shd', { val: 'clear', fill: v.delete('#') }
          },
          _border: lambda { |v|
            props = { sz: 2, val: 'single', color: '000000' }
            vals = v.split
            vals[1] = 'single' if vals[1] == 'solid'
            #
            props[:sz] = @defined_style_conversions[:node][:_sz].call(vals[0])
            props[:val] = vals[1] if vals[1]
            props[:color] = vals[2].delete('#') if vals[2]
            #
            return props
          },
          _sz: lambda { |v|
            return nil unless v
            (2 * Float(v.gsub(/[^\d.]/, '')).ceil).to_s
          },
          'text-align' => ->(v) { return 'jc', v }
        },
        # Styles specific to the Table AST class
        table: {
          'border' => lambda { |v|
            props = @defined_style_conversions[:node][:_border].call(v)
            #
            return 'tblBorders', [
              { top: props }, { start: props }, { bottom: props },
              { end: props }, { insideH: props }, { insideV: props }
            ]
          },
          'margin' => lambda { |v|
            vals = v.split.map do |s|
              @defined_style_conversions[:node][:_sz].call(s)
            end
            #
            props = [vals[0], vals[0], vals[0], vals[0]] if vals.length == 1
            props = [vals[0], vals[1], vals[0], vals[1]] if vals.length == 2
            props = [vals[0], vals[1], vals[2], vals[1]] if vals.length == 3
            props = [vals[0], vals[1], vals[2], vals[3]] if vals.length > 3
            return 'tblCellMar', [
              { top: { w: props[0], type: 'dxa' } },
              { end: { w: props[1], type: 'dxa' } },
              { bottom: { w: props[2], type: 'dxa' } },
              { start: { w: props[3], type: 'dxa' } }
            ]
          },
          'cellspacing' => lambda { |v|
            v = @defined_style_conversions[:node][:_sz].call(v)
            return 'tblCellSpacing', { w: v, type: 'dxa' }
          },
          'width' => lambda { |v|
            v = @defined_style_conversions[:node][:_sz].call(v)
            return 'tblW', { w: v, type: 'dxa' }
          }
        },
        # Styles specific to the TableCell AST class
        table_cell: {
          'border' => lambda { |v|
            value = @defined_style_conversions[:table]['border'].call(v)[1]
            return 'tcBorders', value
          },
          'colspan' => ->(v) { return 'gridSpan', v },
          'margin' => lambda { |v|
            value = @defined_style_conversions[:table]['margin'].call(v)[1]
            return 'tcMar', value
          },
          'rowspan' => lambda { |v|
            return 'vMerge', 'restart' if v == 'start'
            return 'vMerge', v if v == 'continue'
            return 'vMerge', nil if v == 'end'
          },
          'vertical-align' => ->(v) { return 'vAlign', v },
          'white-space' => lambda { |v|
            return 'noWrap', nil if v == 'nowrap'
            return 'tcFitText', 'true' if v == 'fit'
          },
          'width' => lambda { |v|
            value = @defined_style_conversions[:table]['width'].call(v)[1]
            return 'tcW', value
          }
        },
        # Styles specific to the Paragraph AST class
        paragraph: {
          'border' => lambda { |v|
            props = @defined_style_conversions[:node][:_border].call(v)
            #
            return 'pBdr', [
              { top: props }, { bottom: props },
              { left: props }, { right: props }
            ]
          },
          'vertical-align' => ->(v) { return 'textAlignment', v }
        },
        # Styles specific to a run of text
        run: {
          'color' => ->(v) { return 'color', v.delete('#') },
          'font-size' => lambda { |v|
            return 'sz', @defined_style_conversions[:node][:_sz].call(v)
          },
          'font-style' => lambda { |v|
            return 'b', nil if v =~ /bold/
            return 'i', nil if v =~ /italic/
          },
          'font-weight' => ->(v) { return 'b', nil if v =~ /bold/ },
          'text-decoration' => lambda { |v|
            supported = %w[line-through underline]
            props = v.split
            return props[0], 'true' unless supported.include? props[0]
            return 'strike', 'true' if props[0] == 'line-through'
            return 'u', 'single' if props.length == 1
            return 'u', { val: props[1], color: 'auto' } if props.length == 2
            return 'u', { val: props[1], color: props[2].delete('#') }
          },
          'vertical-align' => lambda { |v|
            return 'vertAlign', 'subscript' if v =~ /sub/
            return 'vertAlign', 'superscript' if v =~ /super/
          }
        }
      }
    end
Defines an initial set of CSS -> WordML conversion lambdas stored in
 a nested hash structure where the first key is the AST class and the
 second is the conversion lambda