Skip to content

Commit

Permalink
Implement roughly
Browse files Browse the repository at this point in the history
  • Loading branch information
labocho committed Feb 24, 2012
1 parent 244cec5 commit b609173
Show file tree
Hide file tree
Showing 14 changed files with 466 additions and 11 deletions.
6 changes: 5 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ source "http://rubygems.org"
# Add dependencies required to use your gem here.
# Example:
# gem "activesupport", ">= 2.3.5"
gem "activemodel"

# Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc.
group :development do
gem "rspec", "~> 2.3.0"
gem "bundler", "~> 1.0.0"
gem "jeweler", "~> 1.6.4"
gem "rcov", ">= 0"
gem "simplecov"

gem "ruby-debug19", require: "ruby-debug"
end

56 changes: 56 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
GEM
remote: http://rubygems.org/
specs:
activemodel (3.2.1)
activesupport (= 3.2.1)
builder (~> 3.0.0)
activesupport (3.2.1)
i18n (~> 0.6)
multi_json (~> 1.0)
archive-tar-minitar (0.5.2)
builder (3.0.0)
columnize (0.3.6)
diff-lcs (1.1.3)
git (1.2.5)
i18n (0.6.0)
jeweler (1.6.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
linecache19 (0.5.12)
ruby_core_source (>= 0.1.4)
multi_json (1.0.4)
rake (0.9.2.2)
rspec (2.3.0)
rspec-core (~> 2.3.0)
rspec-expectations (~> 2.3.0)
rspec-mocks (~> 2.3.0)
rspec-core (2.3.1)
rspec-expectations (2.3.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.3.0)
ruby-debug-base19 (0.11.25)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby_core_source (>= 0.1.4)
ruby-debug19 (0.11.6)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby-debug-base19 (>= 0.11.19)
ruby_core_source (0.1.5)
archive-tar-minitar (>= 0.5.2)
simplecov (0.5.4)
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)

PLATFORMS
ruby

DEPENDENCIES
activemodel
bundler (~> 1.0.0)
jeweler (~> 1.6.4)
rspec (~> 2.3.0)
ruby-debug19
simplecov
15 changes: 10 additions & 5 deletions README.rdoc → README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
= movable_type_format
# movable\_type\_format

Description goes here.
Movable Type import / export format parser and builder for Ruby.

Format documentation is below.

* http://www.movabletype.org/documentation/appendices/import-export-format.html
* http://www.movabletype.jp/documentation/appendices/import-export-format.html

## Contributing to movable\_type\_format

== Contributing to movable_type_format

* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
* Fork the project
Expand All @@ -12,7 +17,7 @@ Description goes here.
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

== Copyright
## Copyright

Copyright (c) 2012 labocho. See LICENSE.txt for
further details.
Expand Down
9 changes: 9 additions & 0 deletions lib/movable_type_format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module MovableTypeFormat
autoload :Collection, "movable_type_format/collection"
autoload :Entry, "movable_type_format/entry"
autoload :Field, "movable_type_format/field"
autoload :Next, "movable_type_format/next"
autoload :Parser, "movable_type_format/parser"
autoload :Section, "movable_type_format/section"
extend Parser
end
11 changes: 11 additions & 0 deletions lib/movable_type_format/collection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module MovableTypeFormat
class Collection < Array
def inspect
to_mt
end

def to_mt
map{|e| e.to_mt}.join
end
end
end
19 changes: 19 additions & 0 deletions lib/movable_type_format/entry.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module MovableTypeFormat
class Entry
DELIMITER = "--------\n".freeze
attr_accessor :sections
def self.build_by_sections(sections)
entry = new
entry.sections = sections
entry
end

def inspect
to_mt
end

def to_mt
sections.to_mt + DELIMITER
end
end
end
132 changes: 132 additions & 0 deletions lib/movable_type_format/field.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
require "active_model"
require "time"
require "date"
module MovableTypeFormat
class Field
KEYS = [
"AUTHOR", "TITLE", "BASENAME", "STATUS", "ALLOW", "COMMENTS", "ALLOW PINGS",
"CONVERT BREAKS", "PRIMARY CATEGORY", "CATEGORY", "DATE", "TAGS", "NO ENTRY",
"AUTHOR", "EMAIL", "URL", "IP", "DATE", # for COMMENT
"TITLE", "URL", "IP", "BLOG NAME", "DATE", # for PING
].uniq.freeze
STATUS_VALUES = %w(draft publish future)
ALLOW_COMMENTS_VALUES = %w(0 1)
CONVERT_BREAKS_VALUES = %w(0 1 markdown markdown_with_smartypants richtext textile_2)
DATE_REGEXP = %r{\A(\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d)( AM| PM)?\z}
DATE_FORMAT = "%m/%d/%Y %H:%M:%S"

include ActiveModel::Validations
attr_accessor :key, :value
validates :key, presence: true
validates :value, presence: true

validate do
if key
if KEYS.include?(key) || custom_field?
validate_value
else
errors.add(:key, :format)
end
end
end

def initialize(key = nil, value = nil)
@key, @value = key, value
end

def value
case key
when "DATE"
case @value
when Date, Time
@value
else
parse_date @value
end
when "TAGS"
case @value
when Array
@value
else
parse_tags @value
end
else
@value
end
end

def inspect
to_mt
end

def custom_field?
key && key =~ /\ACF50_.+\z/
end

def to_mt
case key
when "DATE"
case value
when Date, Time
"#{key}: #{value.strftime(DATE_FORMAT)}\n"
else
time = parse_date(value)
"#{key}: #{time.strftime(DATE_FORMAT)}\n"
end
when "TAGS"
case value
when Array
tags = value.map{|tag|
tag = %{"#{tag}"} if tag =~ / /
tag
}.join(",")
"#{key}: #{tags}\n"
else
"#{key}: #{value}\n"
end
else
"#{key}: #{value}\n"
end
end

private
def validate_value
return unless value
case key
when "STATUS"
unless STATUS_VALUES.include?(value.downcase)
errors.add(:value, :inclusion)
end
when "ALLOW COMMENTS"
unless ALLOW_COMMENTS_VALUES.include?(value.to_s)
errors.add(:value, :inclusion)
end
when "CONVERT BREAKS"
unless CONVERT_BREAKS_VALUES.include?(value.to_s)
errors.add(:value, :inclusion)
end
when "DATE"
unless value.is_a?(Date) || value.is_a?(Time) || value =~ DATE_REGEXP
errors.add(:value, :format)
end
end
end

def parse_date(string)
return unless string
string =~ DATE_REGEXP
m, d, y, h, min, s, am_pm = $~.captures
if am_pm == " PM"
h = h.to_i + 12
end
Time.new(y.to_i, m.to_i, d.to_i, h.to_i, min.to_i, s.to_i)
end

def parse_tags(string)
return unless string
string.split(",").map{|tag|
tag =~ /\A"(.+)"\z/ ? $1 : tag
}
end
end
end
15 changes: 15 additions & 0 deletions lib/movable_type_format/next.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Extend Enumerator
module MovableTypeFormat
module Next
def next_if_exists
self.next
rescue StopIteration
end

def next?
!!self.peek
rescue StopIteration
false
end
end
end
77 changes: 77 additions & 0 deletions lib/movable_type_format/parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module MovableTypeFormat
module Parser
module_function
def parse_file(file)
end

def parse(string)
lines = string.lines
lines.extend Next

entries = Collection.new

while lines.next?
entries << parse_entry(lines)
end

entries
end

def parse_entry(lines)
sections = Collection.new
current_field = nil

while lines.next?
case lines.peek
when "--------\n"
lines.next
break
else
sections << parse_section(lines)
end
end

Entry.build_by_sections sections
end

def parse_section(lines)
section = Section.new
context = :head # :fields, :body

while line = lines.next_if_exists
case line
when /^([A-Z0-9 ]+):$/
# section name or single line field
key = $1
case context
when :head
section.name = key
context = :fields
else
section.fields << Field.new(key)
end
when /^([A-Z0-9 ]+): (.+)$/
# single line field or body
key, value = $~.captures
case context
when :head, :fields
section.fields << Field.new(key, value)
context = :fields
else
section.body ||= ""
section.body << line
context = :body
end
when "-----\n"
# end of section
return section
else
section.body ||= ""
section.body << line
context = :body
end
end
section
end
end
end
Loading

0 comments on commit b609173

Please sign in to comment.