simple_document 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Add dependencies to develop your gem here.
4
+ # Include everything needed to run rake, tests, features, etc.
5
+ group :development do
6
+ gem "bundler"
7
+ gem "jeweler"
8
+ gem 'simplecov', :require => false
9
+ gem "ruby-debug19"
10
+ gem "timecop"
11
+ gem "redis"
12
+ end
13
+
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ archive-tar-minitar (0.5.2)
5
+ columnize (0.3.6)
6
+ git (1.2.5)
7
+ jeweler (1.8.3)
8
+ bundler (~> 1.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rdoc
12
+ json (1.6.6)
13
+ linecache19 (0.5.12)
14
+ ruby_core_source (>= 0.1.4)
15
+ multi_json (1.2.0)
16
+ rake (0.9.2.2)
17
+ rdoc (3.12)
18
+ json (~> 1.4)
19
+ redis (2.2.2)
20
+ ruby-debug-base19 (0.11.25)
21
+ columnize (>= 0.3.1)
22
+ linecache19 (>= 0.5.11)
23
+ ruby_core_source (>= 0.1.4)
24
+ ruby-debug19 (0.11.6)
25
+ columnize (>= 0.3.1)
26
+ linecache19 (>= 0.5.11)
27
+ ruby-debug-base19 (>= 0.11.19)
28
+ ruby_core_source (0.1.5)
29
+ archive-tar-minitar (>= 0.5.2)
30
+ simplecov (0.6.1)
31
+ multi_json (~> 1.0)
32
+ simplecov-html (~> 0.5.3)
33
+ simplecov-html (0.5.3)
34
+ timecop (0.3.5)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ bundler
41
+ jeweler
42
+ redis
43
+ ruby-debug19
44
+ simplecov
45
+ timecop
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 radiospiel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = simple_document
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to simple_document
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * 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.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 radiospiel. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "simple_document"
18
+ gem.homepage = "http://github.com/radiospiel/simple_document"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Need some kind of document? Just throw me in.}
21
+ gem.description = %Q{Simplistic documents.}
22
+ gem.email = "eno@open-lab.org"
23
+ gem.authors = ["radiospiel"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'rdoc/task'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "simple_document #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,24 @@
1
+ class ImplementationMissing < NameError; end
2
+
3
+ class Object
4
+ private
5
+
6
+ def implementation_missing!
7
+ calling_method_name = caller[1]
8
+ calling_method_name = $1 if calling_method_name =~ /.*in `(.*)'$/
9
+
10
+ raise ImplementationMissing, "Implementation missing: #{self.class.name}##{calling_method_name}"
11
+ end
12
+ end
13
+
14
+ module Kernel
15
+ private
16
+
17
+ def abstract_method(*syms)
18
+ syms.each do |sym|
19
+ define_method sym do
20
+ raise ImplementationMissing, "#{self.class.name}##{sym}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,105 @@
1
+ class SimpleDocument::FileStore
2
+ class Document < SimpleDocument::Ostruct
3
+ def mtime
4
+ @ostruct.mtime ? Time.parse(@ostruct.mtime.to_s) : File.mtime(self.uri)
5
+ end
6
+ end
7
+
8
+ attr :url
9
+ alias :root :url
10
+
11
+ def initialize(url)
12
+ @url = url
13
+ end
14
+
15
+ # Fetches a document by name from a specific subset with a given
16
+ # locale (or no locale, if the locale parameter is set to nil.)
17
+ def fetch_with_locale(subset, name, locale = nil)
18
+ locale_ext = ".#{locale}" if locale
19
+
20
+ pattern = "#{root}/#{subset}/#{name}#{locale_ext}.{#{FORMAT_BY_EXTENSION.keys.join(",")}}"
21
+ Dir.glob(pattern).sort.
22
+ map do |path| read_from_file(path) end.
23
+ detect(&:active?)
24
+ end
25
+
26
+ # Return a Hash of all documents in a specific subset in this store.
27
+ def all(subset)
28
+ Dir.glob("#{root}/#{subset}/*.{#{FORMAT_BY_EXTENSION.keys.join(",")}}").
29
+ map { |path| read_from_file(path) }.
30
+ select(&:active?).
31
+ group_by(&:name).
32
+ tap { |hash| hash.default = [] }
33
+ end
34
+
35
+ private
36
+
37
+ def dir(subset)
38
+ dir = "#{root}/#{subset}"
39
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
40
+ dir
41
+ end
42
+
43
+ public
44
+
45
+ def store(subset, name, locale, data)
46
+ format, body = data.values_at "format", "body"
47
+ ext = FORMAT_BY_EXTENSION.key(format.to_sym) || raise(ArgumentError, "Unsupported format #{format.inspect}")
48
+ locale_ext = ".#{locale}" if locale
49
+
50
+ path = "#{dir(subset)}/#{name}#{locale_ext}.#{ext}"
51
+
52
+ File.open(path, "w") do |file|
53
+ file.write data.to_yaml unless data.empty?
54
+ file.write "---\n"
55
+ file.write body
56
+ end
57
+
58
+ fetch_with_locale(subset, name, locale)
59
+ end
60
+
61
+ private
62
+
63
+ FORMAT_BY_EXTENSION = {
64
+ "md" => :markdown,
65
+ "html" => :plain,
66
+ "erb" => :erb
67
+ }
68
+
69
+ def header_and_body_from_document(path)
70
+ content = File.read(path).force_encoding('UTF-8')
71
+ lines = StringIO.new(content).readlines
72
+ lines.shift if lines.first =~ /^---/
73
+
74
+ header = []
75
+
76
+ while (line = lines.shift) && line !~ /^---/ do
77
+ header << line
78
+ end
79
+
80
+ if lines.empty?
81
+ [ nil, header.join ]
82
+ else
83
+ [ header.join, lines.join ]
84
+ end
85
+ end
86
+
87
+ # read a simple document from a file
88
+ def read_from_file(path)
89
+ header, body = header_and_body_from_document(path)
90
+ header = header ? YAML::load(header) : {}
91
+
92
+ attributes = attributes_from_path(path) || raise("Cannot parse path: #{path.inspect}")
93
+
94
+ Document.new header.merge(attributes).merge(:body => body)
95
+ end
96
+
97
+ def attributes_from_path(path)
98
+ return unless File.basename(path) =~ /^([^.]+)\.((\w\w)\.)?(\w+)$/
99
+
100
+ name, locale, ext = $1, $3, $4
101
+ return unless format = FORMAT_BY_EXTENSION[ext]
102
+
103
+ { :locale => locale, :name => name, :uri => path, :format => format }
104
+ end
105
+ end
@@ -0,0 +1,20 @@
1
+ require 'ostruct'
2
+ require 'forwardable'
3
+
4
+ class SimpleDocument::Ostruct < SimpleDocument
5
+ extend Forwardable
6
+
7
+ def initialize(data)
8
+ @ostruct = OpenStruct.new(data)
9
+ end
10
+
11
+ delegate [:header, :body, :name, :format, :uri] => :@ostruct
12
+
13
+ def active?
14
+ true
15
+ end
16
+
17
+ def mtime
18
+ @ostruct.mtime && Time.parse(@ostruct.mtime)
19
+ end
20
+ end
@@ -0,0 +1,85 @@
1
+ require_relative "abstract_method"
2
+
3
+ class SimpleDocument
4
+ abstract_method :header
5
+ abstract_method :body
6
+ abstract_method :name
7
+ abstract_method :format
8
+ abstract_method :active?
9
+ abstract_method :mtime
10
+
11
+ singleton_class.class_eval do
12
+ def url
13
+ @store.url if @store
14
+ end
15
+
16
+ def url=(url)
17
+ @store = FileStore.new(url)
18
+ end
19
+
20
+ def store
21
+ @store || raise("Missing SimpleDocument.url setting")
22
+ end
23
+
24
+ def uncache
25
+ self.url = store.url if store
26
+ end
27
+
28
+ # Return a Hash of all documents in a specific subset in this store.
29
+ # The Hash keys are the document names, the hash values are an Array
30
+ # of documents for this name, with potentially different locales.
31
+ def all(subset)
32
+ store.all(subset)
33
+ end
34
+
35
+ # Stores a single document in a specific subset in this store.
36
+ def write(name, data)
37
+ subset, name = parse_name(name)
38
+
39
+ # stringify keys
40
+ data = data.inject({}) { |hash, (k,v)| hash.update(k.to_s => v) }
41
+ locale = data.delete "locale"
42
+
43
+ raise(ArgumentError, "Missing format entry") unless data.key?("format")
44
+
45
+ store.store(subset, name, locale, data)
46
+ end
47
+
48
+ # Fetches a document by name from a specific subset. If a localize
49
+ # is set it tries to load a localized variant of the document first.
50
+ # If there is no such document, it then tries to load a non-localized
51
+ # variant of the document.
52
+ #
53
+ # The method returns nil if there is no such document.
54
+ def read(name, options = {})
55
+ subset, name = parse_name(name)
56
+
57
+ # stringify keys
58
+ options = options.inject({}) { |hash, (k,v)| hash.update(k.to_s => v) }
59
+ locale = options.delete "locale"
60
+
61
+ (locale && store.fetch_with_locale(subset, name, locale)) ||
62
+ store.fetch_with_locale(subset, name, nil)
63
+ end
64
+
65
+ # Fetches a document by name from a specific subset, using #fetch.
66
+ # In opposite to #fetch this method raises an Errno::ENOENT
67
+ # exception if there is no such document.
68
+ def read!(name, options = {})
69
+ read(name, options) || raise(Errno::ENOENT, "SimpleDocument[#{url}]/#{name}")
70
+ end
71
+
72
+ private
73
+
74
+ def parse_name(name)
75
+ if name =~ /^([-a-zA-Z0-9]+)\/([-a-zA-Z0-9]+)$/
76
+ return [$1, $2]
77
+ end
78
+
79
+ raise ArgumentError, "Invalid name #{name.inspect}"
80
+ end
81
+ end
82
+ end
83
+
84
+ require_relative "simple_document/ostruct"
85
+ require_relative "simple_document/file_store"
@@ -0,0 +1,147 @@
1
+ require_relative 'test_helper'
2
+
3
+ DIR = File.expand_path File.dirname(__FILE__)
4
+
5
+ class SimpleDocument::FileStoreTest < Test::Unit::TestCase
6
+ def setup
7
+ SimpleDocument.url = "#{DIR}/fixtures"
8
+
9
+ # Clean writing directory
10
+ FileUtils.rm_rf("#{DIR}/fixtures/writing")
11
+ end
12
+
13
+ def teardown
14
+ File.unlink @store.path if @store
15
+ end
16
+
17
+ # -- load single documents ------------------------------------------------
18
+
19
+ def test_load_about
20
+ doc = SimpleDocument.read "folder/about"
21
+
22
+ assert_equal "#{DIR}/fixtures/folder/about.md", doc.uri
23
+ assert_equal :markdown, doc.format
24
+ assert_equal "A english \"about\"\n", doc.body
25
+
26
+ assert_equal nil, doc.header
27
+ assert_equal "about", doc.name
28
+ assert_equal true, doc.active?
29
+ assert_equal File.mtime(doc.uri), doc.mtime
30
+ end
31
+
32
+ # load document in a specific locale
33
+ def test_load_about_de
34
+ doc = SimpleDocument.read "folder/about", :locale => "de"
35
+
36
+ assert_equal "#{DIR}/fixtures/folder/about.de.md", doc.uri
37
+ assert_equal :markdown, doc.format
38
+ assert_equal "Ein deutsches \"about\"\n", doc.body
39
+
40
+ assert_equal nil, doc.header
41
+ assert_equal "about", doc.name
42
+ assert_equal true, doc.active?
43
+ assert_equal File.mtime(doc.uri), doc.mtime
44
+ end
45
+
46
+ # fallback to base document in a specific, but missing locale
47
+ def test_load_about_missing_locale
48
+ doc = SimpleDocument.read "folder/about", :locale => "fr"
49
+
50
+ assert_equal "#{DIR}/fixtures/folder/about.md", doc.uri
51
+ end
52
+
53
+ # load document with headers
54
+ def test_load_headered
55
+ doc = SimpleDocument.read "folder/headered"
56
+
57
+ assert_equal "#{DIR}/fixtures/folder/headered.md", doc.uri
58
+ assert_equal :markdown, doc.format
59
+ assert_equal "A document with a header.\n", doc.body
60
+
61
+ assert_equal nil, doc.header
62
+ assert_equal "headered", doc.name
63
+ assert_equal true, doc.active?
64
+ assert_equal Time.parse("2012-01-01"), doc.mtime
65
+ end
66
+
67
+ # load missing document
68
+ def test_load_missing!
69
+ assert_raise(Errno::ENOENT) {
70
+ SimpleDocument.read! "missing-folder/about"
71
+ }
72
+
73
+ assert_raise(Errno::ENOENT) {
74
+ SimpleDocument.read! "folder/missing-about"
75
+ }
76
+ end
77
+
78
+ def test_load_missing
79
+ assert_nil SimpleDocument.read("missing-folder/about")
80
+ assert_nil SimpleDocument.read("folder/missing-about")
81
+ end
82
+
83
+ # -- fetch collections ------------------------------------------------
84
+
85
+ # fetch collection
86
+ def test_missing_collection
87
+ docs = SimpleDocument.all "missing-folder"
88
+ assert_equal({}, docs)
89
+ end
90
+
91
+ def test_collection
92
+ # Return a Hash of all documents in a specific subset in this store.
93
+ # The Hash keys are the document names, the hash values are an Array
94
+ # of documents for this name, with potentially different locales.
95
+
96
+ docs = SimpleDocument.all "folder"
97
+ assert_kind_of(Hash, docs)
98
+ assert_equal(%w(about headered), docs.keys.sort)
99
+ assert_equal(2, docs.count)
100
+ assert_equal([], docs["missing"])
101
+ end
102
+
103
+ # -- writing ------------------------------------------------
104
+
105
+ def test_write_fails
106
+ # Make sure we are blank.
107
+ assert_raise(Errno::ENOENT) { SimpleDocument.read! "writing/foo" }
108
+
109
+ # Missing format
110
+ assert_raise(ArgumentError) { SimpleDocument.write "writing/foo", :body => "The body" }
111
+
112
+ # Invalid format
113
+ assert_raise(ArgumentError) { SimpleDocument.write "writing/foo", :body => "The body", :format => "yahoo!" }
114
+
115
+ # Invalid names
116
+ assert_raise(ArgumentError) { SimpleDocument.write "wba/../dd", "12.kjsh", :body => "The body", :format => "markdown" }
117
+ end
118
+
119
+ def test_write
120
+ # Make sure we are blank.
121
+ assert_raise(Errno::ENOENT) { SimpleDocument.read! "writing/foo" }
122
+
123
+ doc = SimpleDocument.write "writing/foo", :body => "The body", :format => "markdown"
124
+ assert_equal("foo", doc.name)
125
+ assert_equal("The body", doc.body)
126
+ assert_equal(true, doc.active?)
127
+
128
+ doc = SimpleDocument.read! "writing/foo", :locale => "de"
129
+ assert_equal("foo", doc.name)
130
+ assert_equal("The body", doc.body)
131
+ assert_equal(true, doc.active?)
132
+ end
133
+
134
+ # -- uncache ------------------------------------------------
135
+
136
+ def test_uncache
137
+ store_1 = SimpleDocument.store
138
+ store_2 = SimpleDocument.store
139
+ SimpleDocument.uncache
140
+ store_3 = SimpleDocument.store
141
+
142
+ assert_equal(store_1.object_id, store_2.object_id)
143
+ assert_not_equal(store_1.object_id, store_3.object_id)
144
+
145
+ assert_equal(store_1.url, store_3.url)
146
+ end
147
+ end
@@ -0,0 +1 @@
1
+ Ein deutsches "about"
@@ -0,0 +1 @@
1
+ A english "about"
@@ -0,0 +1,3 @@
1
+ mtime: 2012-01-01
2
+ ---
3
+ A document with a header.
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ require 'ruby-debug'
12
+ require 'simplecov'
13
+ require 'timecop'
14
+ require 'test/unit'
15
+ SimpleCov.start do
16
+ add_filter "test/*.rb"
17
+ add_filter "lib/abstract_method.rb"
18
+ end
19
+
20
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
21
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
22
+ require 'simple_document'
23
+
24
+ module SimpleDocument::TestCase
25
+ def test_simple_document_kindof
26
+ assert store.kind_of?(SimpleDocument)
27
+ end
28
+
29
+ # def test_simple_document
30
+ # assert_equal(nil, simple_document.fetch("bar"))
31
+ #
32
+ # assert_equal("foo", simple_document.store("bar", "foo"))
33
+ # assert_equal("foo", simple_document.fetch("bar"))
34
+ #
35
+ # done = 0
36
+ # assert_equal "baz", simple_document.cached("key") { done += 1; "baz" }
37
+ # assert_equal 1, done
38
+ # assert_equal "baz", simple_document.cached("key") { done += 1; "baz" }
39
+ # assert_equal 1, done
40
+ #
41
+ # assert_equal(nil, simple_document.store("bar", nil))
42
+ # assert_equal(nil, simple_document.fetch("bar"))
43
+ # end
44
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_document
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - radiospiel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70336244947520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70336244947520
25
+ - !ruby/object:Gem::Dependency
26
+ name: jeweler
27
+ requirement: &70336244946980 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70336244946980
36
+ - !ruby/object:Gem::Dependency
37
+ name: simplecov
38
+ requirement: &70336244946360 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70336244946360
47
+ - !ruby/object:Gem::Dependency
48
+ name: ruby-debug19
49
+ requirement: &70336244940120 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70336244940120
58
+ - !ruby/object:Gem::Dependency
59
+ name: timecop
60
+ requirement: &70336244939540 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70336244939540
69
+ - !ruby/object:Gem::Dependency
70
+ name: redis
71
+ requirement: &70336244938900 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70336244938900
80
+ description: Simplistic documents.
81
+ email: eno@open-lab.org
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files:
85
+ - LICENSE.txt
86
+ - README.rdoc
87
+ files:
88
+ - Gemfile
89
+ - Gemfile.lock
90
+ - LICENSE.txt
91
+ - README.rdoc
92
+ - Rakefile
93
+ - VERSION
94
+ - lib/abstract_method.rb
95
+ - lib/simple_document.rb
96
+ - lib/simple_document/file_store.rb
97
+ - lib/simple_document/ostruct.rb
98
+ - test/file_store_test.rb
99
+ - test/fixtures/folder/about.de.md
100
+ - test/fixtures/folder/about.md
101
+ - test/fixtures/folder/headered.md
102
+ - test/test_helper.rb
103
+ homepage: http://github.com/radiospiel/simple_document
104
+ licenses:
105
+ - MIT
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ segments:
117
+ - 0
118
+ hash: 2569138236874985957
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.10
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Need some kind of document? Just throw me in.
131
+ test_files: []