class BookmarkMachine::BookmarkDocument

BookmarkDocument implements SAX callbacks for parsing messy bookmark files. It turns out that a SAX parser is more resilient to bizarre inputs than the typical Nokogiri parser since it doesn’t bother itself with the document structure.

Attributes

bookmarks[R]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/bookmark_machine/netscape_parser.rb, line 37
def initialize
  super
  
  @folders = []
  @bookmarks = []
  @current_bookmark = nil
  
  reset_state
end

Public Instance Methods

characters(string) click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 71
def characters(string)
  @text << string if @state
end
done() click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 96
def done
  case @state
  when :bookmark
    @current_bookmark.name = @text.strip
    @bookmarks << @current_bookmark
    @current_bookmark = nil
    reset_state
    
  when :folder
    @folders << @text.strip
    reset_state
    
  when :description
    description = @text.strip
    @bookmarks.last.description = description unless description == ""
    reset_state
    
  end
end
end_document() click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 67
def end_document
  done
end
end_element(name, attrs = []) click to toggle source

Only one closing element has semantic meaning, a closed DL, which indicates the end of a folder.

# File lib/bookmark_machine/netscape_parser.rb, line 60
def end_element(name, attrs = [])
  case name
  when "dl" then pop_folder
  else           done
  end
end
epoch_time(seconds) click to toggle source

Converts from epoch seconds to a Time object. Returns nil on a nil input.

# File lib/bookmark_machine/netscape_parser.rb, line 128
def epoch_time(seconds)
  Time.at(seconds.to_i) if seconds
end
pop_folder() click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 116
def pop_folder
  @folders.pop
  done
end
reset_state() click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 121
def reset_state
  @text = ""
  @state = nil
end
start_bookmark(attrs) click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 75
def start_bookmark(attrs)
  attrs = Hash[attrs]
  
  @current_bookmark = Bookmark.new(attrs['href'])
  @current_bookmark.created_at = epoch_time(attrs['add_date'])
  @current_bookmark.updated_at = epoch_time((attrs['last_modified'] || attrs['add_date']))
  @current_bookmark.icon = attrs['icon'] || attrs['icon_uri']
  @current_bookmark.tags = tagged_text(attrs['tags'])
  @current_bookmark.folders = @folders.clone
  
  @state = :bookmark
end
start_description(attrs) click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 92
def start_description(attrs)
  @state = :description
end
start_element(name, attrs = []) click to toggle source

Only three elements have semantic meaning, A, H3, and DD, representing Folder names, Bookmarks, and Descriptions.

# File lib/bookmark_machine/netscape_parser.rb, line 49
def start_element(name, attrs = [])
  case name
  when "a"  then start_bookmark(attrs)
  when "h3" then start_folder(attrs)
  when "dd" then start_description(attrs)
  else           done
  end
end
start_folder(attrs) click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 88
def start_folder(attrs)
  @state = :folder
end
tagged_text(str) click to toggle source
# File lib/bookmark_machine/netscape_parser.rb, line 132
def tagged_text(str)
  str.split(",").map{|t| t.strip} if str
end