XOXO

XOXO is a Ruby XOXO parser and generator. It provides a Ruby API similar to Marshal and YAML (though more specific) to load and dump XOXO, an simple, open outline format written in standard XHTML and suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML.

Methods
Public Class methods
dump(struct, options={})

Return a XOXO string corresponding to the Ruby object struct, translated to the following rules:

  • Arrays become ordered lists <ol>.
  • Hashes become definition lists <dl>, keys are stringified with to_s.
  • Everything else becomes stringified with to_s and wrapped in appropriate list elements (<li> or <dt>/<dd>).

Additionally, you can pass these options on the options hash:

:html_wrap => true:Wrap the XOXO with a basic XHTML 1.0 Transitional header.
:css => css:Reference css as stylesheet for the wrapped XOXO document.
# File lib/facets/xoxo.rb, line 71
  def self.dump(struct, options={})
    struct = [struct]  unless struct.kind_of? Array

    if options[:html_wrap]
      result = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\nhttp://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head profile=\"\"><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n".strip
      if options[:css]
        result << %Q[<style type="text/css" >@import "#{options[:css]}";</style>]
      end

      result << "</head><body>" << make_xoxo(struct, 'xoxo') << "</body></html>"
    else
      result = make_xoxo(struct, 'xoxo')
    end

    result
  end
load(xoxo)

Load and return a XOXO structure from the String, IO or StringIO or xoxo.

# File lib/facets/xoxo.rb, line 48
  def self.load(xoxo)
    structs = Parser.new(xoxo).parse.structs
    while structs.kind_of?(Array) && structs.size == 1
      structs = structs.first
    end
    structs
  end
Private Class methods
make_xoxo(struct, class_name=nil)
# File lib/facets/xoxo.rb, line 95
  def self.make_xoxo(struct, class_name=nil)
    s = ''
    case struct
    when Array
      if class_name
        s << %Q[<ol class="#{class_name}">]
      else
        s << "<ol>"
      end
      struct.each { |item|
        s << "<li>" << make_xoxo(item) << "</li>"
      }
      s << "</ol>"

    when Hash
      d = struct.dup
      if d.has_key? 'url'
        s << '<a href="' << d['url'].to_s << '" '
        text = d.fetch('text') { d.fetch('title', d['url']) }
        %w[title rel type].each { |tag|
          if d.has_key? tag
            s << tag.to_s << '="' << make_xoxo(d.delete(tag)) << '" '
          end
        }
        s << '>' << make_xoxo(text) << '</a>'
        d.delete 'text'
        d.delete 'url'
      end

      unless d.empty?
        s << "<dl>"
        d.each { |key, value|
          s << "<dt>" << key.to_s << "</dt><dd>" << make_xoxo(value) << "</dd>"
        }
        s << "</dl>"
      end

    when String
      s << struct

    else
      s << struct.to_s          # too gentle?
    end

    s
  end