mill 0.11 → 0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -1
  3. data/LICENSE +1 -1
  4. data/Rakefile +1 -2
  5. data/TODO.md +4 -0
  6. data/bin/mill +1 -27
  7. data/lib/mill/command.rb +13 -0
  8. data/lib/mill/commands/build.rb +17 -0
  9. data/lib/mill/commands/check.rb +16 -0
  10. data/lib/mill/commands/diff.rb +18 -0
  11. data/lib/mill/commands/list.rb +20 -0
  12. data/lib/mill/commands/snapshot.rb +20 -0
  13. data/lib/mill/commands/tree.rb +17 -0
  14. data/lib/mill/commands/types.rb +18 -0
  15. data/lib/mill/commands/upload.rb +24 -0
  16. data/lib/mill/config.rb +27 -0
  17. data/lib/mill/resource.rb +81 -81
  18. data/lib/mill/resources/blob.rb +4 -0
  19. data/lib/mill/resources/feed.rb +5 -13
  20. data/lib/mill/resources/image.rb +10 -18
  21. data/lib/mill/resources/markdown.rb +20 -0
  22. data/lib/mill/resources/markup.rb +62 -0
  23. data/lib/mill/resources/page.rb +140 -0
  24. data/lib/mill/resources/redirect.rb +17 -16
  25. data/lib/mill/resources/robots.rb +3 -4
  26. data/lib/mill/resources/sitemap.rb +3 -5
  27. data/lib/mill/resources/stylesheet.rb +4 -4
  28. data/lib/mill/resources/textile.rb +27 -0
  29. data/lib/mill/resources.rb +89 -0
  30. data/lib/mill/site.rb +181 -251
  31. data/lib/mill.rb +28 -8
  32. data/mill.gemspec +22 -17
  33. data/test/content/a.md +3 -0
  34. data/test/content/b/ba.md +3 -0
  35. data/test/content/b/bb.md +3 -0
  36. data/test/content/b/index.md +3 -0
  37. data/test/content/c.md +4 -0
  38. data/test/content/d.md +4 -0
  39. data/test/content/index.md +3 -0
  40. data/test/main_test.rb +68 -0
  41. data/test/mill.yaml +8 -0
  42. metadata +189 -40
  43. data/TODO.txt +0 -61
  44. data/lib/mill/html_helpers.rb +0 -122
  45. data/lib/mill/navigator.rb +0 -61
  46. data/lib/mill/resources/dir.rb +0 -31
  47. data/lib/mill/resources/google_site_verification.rb +0 -30
  48. data/lib/mill/resources/text.rb +0 -207
  49. data/lib/mill/version.rb +0 -5
data/lib/mill/site.rb CHANGED
@@ -2,360 +2,290 @@ module Mill
2
2
 
3
3
  class Site
4
4
 
5
- attr_accessor :input_dir
6
- attr_accessor :output_dir
7
- attr_accessor :site_rsync
8
- attr_accessor :site_title
9
- attr_accessor :site_uri
10
- attr_accessor :site_email
11
- attr_accessor :site_control_date
12
- attr_accessor :html_version
13
- attr_accessor :feed_resource
14
- attr_accessor :sitemap_resource
15
- attr_accessor :robots_resource
16
- attr_accessor :shorten_uris
17
- attr_accessor :make_feed
18
- attr_accessor :make_sitemap
19
- attr_accessor :make_robots
20
- attr_accessor :allow_robots
21
- attr_accessor :htpasswd_file
22
- attr_accessor :navigator
23
- attr_accessor :resource_classes
24
- attr_accessor :redirects
25
- attr_accessor :resources
26
-
27
- DefaultResourceClasses = ObjectSpace.each_object(Class).select { |c| c < Resource }
28
-
29
- def initialize(input_dir: 'content',
30
- output_dir: 'public_html',
31
- site_rsync: nil,
32
- site_title: nil,
33
- site_uri: 'http://localhost',
34
- site_email: nil,
35
- site_control_date: Date.today.to_s,
36
- html_version: :html4_transitional,
37
- shorten_uris: true,
38
- make_feed: true,
39
- make_sitemap: true,
40
- make_robots: true,
41
- allow_robots: true,
42
- htpasswd_file: nil,
43
- navigator: nil,
44
- google_site_verification: nil,
45
- resource_classes: [],
46
- redirects: {})
47
-
48
- @input_dir = Path.new(input_dir)
49
- @output_dir = Path.new(output_dir)
50
- @site_rsync = site_rsync
51
- @site_title = site_title
52
- @site_uri = Addressable::URI.parse(site_uri)
53
- @site_email = Addressable::URI.parse(site_email) if site_email
54
- @site_control_date = Date.parse(site_control_date)
55
- @html_version = html_version
56
- @shorten_uris = shorten_uris
57
- @make_feed = make_feed
58
- @make_sitemap = make_sitemap
59
- @make_robots = make_robots
60
- @allow_robots = allow_robots
61
- @htpasswd_file = htpasswd_file ? Path.new(htpasswd_file) : nil
62
- @resource_classes = resource_classes
63
- @navigator = navigator
64
- @google_site_verification = google_site_verification
65
- @redirects = redirects
66
-
67
- @resources = []
68
- @resources_by_uri = {}
69
- build_file_types
70
- end
71
-
72
- def build_file_types
5
+ attr_accessor :config
6
+ attr_reader :feed_resource
7
+ attr_reader :sitemap_resource
8
+ attr_reader :robots_resource
9
+ attr_reader :redirects
10
+ attr_reader :resources
11
+ attr_reader :file_types
12
+
13
+ def self.load(dir=nil)
14
+ config = BaseConfig.make(dir: dir)
15
+ config = config.load_yaml(config.dir / ConfigFileName)
16
+ site_file = config.dir / config.code_dir / 'site.rb'
17
+ klass = load_site_class(site_file)
18
+ klass.new(config)
19
+ end
20
+
21
+ def self.load_site_class(site_file)
22
+ Kernel.load(site_file.expand_path.to_s) if site_file.exist?
23
+ site_classes = subclasses
24
+ if site_classes.length == 0
25
+ self
26
+ elsif site_classes.length > 1
27
+ raise Error, "More than one #{self.class} class defined"
28
+ else
29
+ site_classes.first
30
+ end
31
+ end
32
+
33
+ def initialize(config)
34
+ @config = config
35
+ @redirects = {}
36
+ @resources = Resources.new
37
+ make_file_types
38
+ end
39
+
40
+ def inspect
41
+ "<#{self.class}>"
42
+ end
43
+
44
+ def input_dir = @config.dir / @config.input_dir
45
+ def output_dir = @config.dir / @config.output_dir
46
+ def site_uri = @config.site_uri
47
+ def site_rsync = @config.site_rsync
48
+ def site_title = @config.site_title
49
+ def site_email = @config.site_email
50
+ def site_postal = @config.site_postal
51
+ def site_phone = @config.site_phone
52
+ def site_instagram = @config.site_instagram
53
+ def site_control_date = @config.site_control_date
54
+ def html_version = @config.html_version
55
+ def make_error? = @config.make_error
56
+ def make_feed? = @config.make_feed
57
+ def make_sitemap? = @config.make_sitemap
58
+ def make_robots? = @config.make_robots
59
+ def allow_robots? = @config.allow_robots
60
+
61
+ def make_file_types
73
62
  @file_types = {}
74
- (DefaultResourceClasses + @resource_classes).each do |resource_class|
63
+ get_file_types(Resource)
64
+ end
65
+
66
+ def get_file_types(klass)
67
+ klass.subclasses.each do |resource_class|
75
68
  resource_class.const_get(:FileTypes).each do |type|
76
69
  @file_types[type] = resource_class
77
70
  end
71
+ get_file_types(resource_class)
78
72
  end
79
73
  end
80
74
 
81
75
  def add_resource(resource)
76
+ # ;;warn "adding #{resource.class} as #{resource.path}"
82
77
  resource.site = self
78
+ resource.load
83
79
  @resources << resource
84
- @resources_by_uri[resource.uri] = resource
85
- # ;;warn "added #{resource} as #{resource.uri}"
86
- end
87
-
88
- def delete_resource(resource)
89
- @resources.delete(resource)
90
- @resources_by_uri.delete(resource.uri)
91
80
  end
92
81
 
93
- def find_resource(uri)
94
- uri = Addressable::URI.parse(uri.to_s) unless uri.kind_of?(Addressable::URI)
95
- resource = @resources_by_uri[uri]
96
- if resource.nil? && @shorten_uris
97
- uri.path = uri.path.sub(%r{\.html$}, '')
98
- resource = @resources_by_uri[uri]
99
- end
100
- resource
101
- end
102
-
103
- def resource_for_file(path)
104
- find_resource(
105
- URI.parse(
106
- '/' + URI.encode(
107
- path.relative_to(@output_dir).to_s
108
- )
109
- )
110
- )
82
+ def find_resource(path)
83
+ @resources[path]
111
84
  end
112
85
 
113
- def home_resource
114
- find_resource('/')
86
+ def root_resource
87
+ @resources['/']
115
88
  end
116
89
 
117
90
  def tag_uri
118
91
  'tag:%s:' % [
119
92
  [
120
- @site_uri.host.downcase,
121
- @site_control_date
93
+ site_uri.host.downcase,
94
+ site_control_date
122
95
  ].join(','),
123
96
  ]
124
97
  end
125
98
 
126
99
  def feed_author_name
127
- @site_title
100
+ site_title
128
101
  end
129
102
 
130
103
  def feed_author_uri
131
- @site_uri
104
+ site_uri
132
105
  end
133
106
 
134
107
  def feed_author_email
135
- @site_email
108
+ site_email
136
109
  end
137
110
 
138
111
  def feed_resources
139
- public_resources.sort_by(&:date)
112
+ primary_resources
140
113
  end
141
114
 
142
- def public_resources
143
- @resources.select(&:public)
115
+ def sitemap_resources
116
+ primary_resources
144
117
  end
145
118
 
146
- def private_resources
147
- @resources.select { |r| r.kind_of?(Resource::Text) && !r.public }
148
- end
149
-
150
- def redirect_resources
151
- @resources.select { |r| r.kind_of?(Resource::Redirect) }
152
- end
153
-
154
- def make
155
- build
156
- save
157
- end
158
-
159
- def list
160
-
161
- list_keys = {
162
- class: proc { |v| v.to_s.sub(/::Resource::/, '::') },
163
- input_file: proc { |v| v.relative_to(@input_dir) },
164
- output_file: proc { |v| v.relative_to(@output_dir) },
165
- public: proc { |v| v },
166
- content: proc { |v| '%dKB' % (v.to_s.length / 1024.0).ceil },
167
- }
168
-
169
- build
170
- list = @resources.map do |resource|
171
- Hash[
172
- list_keys.map do |k, p|
173
- v = resource.send(k)
174
- [
175
- k,
176
- v ? p.call(v).to_s : '-'
177
- ]
178
- end
179
- ]
180
- end
181
- format = list_keys.keys.map do |key|
182
- '%%-%ds' % list.map { |item| item[key].length }.max
183
- end.join(' ')
184
- puts format % list_keys.keys
185
- list.each do |item|
186
- puts format % item.values
187
- end
119
+ def primary_resources
120
+ @resources.select(&:primary?).sort_by(&:date)
188
121
  end
189
122
 
190
123
  def build
191
- import_resources
192
124
  load_resources
125
+ convert_resources
193
126
  build_resources
127
+ check
194
128
  end
195
129
 
196
- def import_resources
130
+ def load_resources
197
131
  add_files
198
132
  add_redirects
199
- add_google_site_verification if @google_site_verification
200
- add_feed if @make_feed
201
- add_sitemap if @make_sitemap
202
- add_robots if @make_robots
203
- add_htpasswd if @htpasswd_file
204
- end
205
-
206
- def load_resources
207
- on_each_resource do |resource|
208
- # ;;warn "#{resource.uri}: loading"
209
- resource.load
210
- end
133
+ add_error if make_error?
134
+ add_feed if make_feed?
135
+ add_sitemap if make_sitemap?
136
+ add_robots if make_robots?
211
137
  end
212
138
 
213
139
  def build_resources
214
- on_each_resource do |resource|
215
- # ;;warn "#{resource.uri}: building"
140
+ @resources.each do |resource|
141
+ # ;;warn "#{resource.path}: building"
216
142
  resource.build
217
143
  end
218
144
  end
219
145
 
220
- def save
221
- clean
222
- @output_dir.mkpath
223
- on_each_resource do |resource|
224
- # ;;warn "#{resource.uri}: saving"
225
- resource.save
146
+ def convert_resources
147
+ @resources.select { |r| r.respond_to?(:convert) }.each do |resource|
148
+ new_resource = resource.convert
149
+ @resources.delete(resource)
150
+ if new_resource
151
+ new_resource.load
152
+ add_resource(new_resource)
153
+ end
226
154
  end
227
155
  end
228
156
 
229
- def clean
230
- if @output_dir.exist?
231
- @output_dir.children.reject { |p| p.basename.to_s == '.git' }.each do |path|
157
+ def save
158
+ if output_dir.exist?
159
+ output_dir.children.reject { |p| p.basename.to_s == '.git' }.each do |path|
232
160
  path.rm_rf
233
161
  end
162
+ else
163
+ output_dir.mkpath
234
164
  end
235
- end
236
-
237
- def check
238
- build
239
- checker = WebChecker.new(site_uri: @site_uri, site_dir: @output_dir)
240
- end
241
-
242
- def snapshot
243
- @output_dir.chdir do
244
- system('git',
245
- 'add',
246
- '.')
247
- system('git',
248
- 'commit',
249
- '-a',
250
- '-m',
251
- 'Update.')
165
+ @resources.each do |resource|
166
+ # ;;warn "#{resource.path}: saving"
167
+ resource.save
252
168
  end
253
169
  end
254
170
 
255
- def diff
256
- @output_dir.chdir do
257
- system('git',
258
- 'diff')
171
+ def check(external: false)
172
+ build if @resources.empty?
173
+ @resources.of_class(Resource::Page).each do |resource|
174
+ resource.links.each do |link|
175
+ begin
176
+ check_uri(link, external: external)
177
+ rescue Error => e
178
+ warn "#{resource.path}: #{e}"
179
+ end
180
+ end
259
181
  end
260
182
  end
261
183
 
262
- def upload
263
- raise "site_rsync not defined" unless @site_rsync
264
- system('rsync',
265
- '--progress',
266
- '--verbose',
267
- '--archive',
268
- '--exclude=.git',
269
- '--delete-after',
270
- @output_dir.to_s,
271
- @site_rsync)
184
+ def resource_class_for_file(file)
185
+ types = MIME::Types.type_for(file.to_s)
186
+ content_type = types.last&.content_type or raise Error, "Can't determine content type: #{file.to_s.inspect}"
187
+ resource_class_for_type(content_type) or raise Error, "Unknown file type: #{file.to_s.inspect} (#{types.join(', ')})"
272
188
  end
273
189
 
274
- def on_each_resource(&block)
275
- @resources.each do |resource|
276
- old_uri = resource.uri.dup
277
- begin
278
- yield(resource)
279
- rescue Error => e
280
- raise e, "#{resource.input_file || '-'} (#{old_uri}): #{e}"
281
- end
282
- if resource.uri != old_uri
283
- # ;;warn "URI changed: #{old_uri} => #{resource.uri}"
284
- @resources_by_uri.delete(old_uri)
285
- @resources_by_uri[resource.uri] = resource
286
- end
287
- end
190
+ def resource_class_for_type(type)
191
+ @file_types[type]
288
192
  end
289
193
 
290
194
  private
291
195
 
292
- def resource_class_for_file(file)
293
- type = MIME::Types.of(file.to_s).first
294
- if type && (klass = @file_types[type.content_type])
295
- klass
296
- else
297
- raise Error, "Unknown file type: #{file.to_s.inspect} (#{MIME::Types.of(file.to_s).join(', ')})"
298
- end
299
- end
300
-
301
196
  def add_files
302
- raise Error, "Input path not found: #{@input_dir}" unless @input_dir.exist?
303
- @input_dir.find do |input_file|
197
+ raise Error, "Input directory not found: #{input_dir}" unless input_dir.exist?
198
+ input_dir.find do |input_file|
304
199
  if input_file.basename.to_s[0] == '.'
305
200
  Find.prune
201
+ elsif input_file.basename.to_s == "Icon\r"
202
+ # skip macOS garbage file
306
203
  elsif input_file.directory?
307
- # skip
204
+ # skip directories
308
205
  else (klass = resource_class_for_file(input_file))
309
- resource = klass.new(
310
- input_file: input_file,
311
- output_file: @output_dir / input_file.relative_to(@input_dir))
206
+ resource = klass.new(input: input_file, path: '/' + input_file.relative_to(input_dir).to_s)
312
207
  add_resource(resource)
313
208
  end
314
209
  end
315
210
  end
316
211
 
212
+ def add_error
213
+ input = Simple::Builder.parse_html_document(
214
+ Kramdown::Document.new(
215
+ %Q{
216
+ Something went wrong.
217
+ The page you were looking for doesn’t exist or couldn’t be displayed.
218
+ Please try another option.
219
+ }.gsub(/\s+/, ' ').strip
220
+ ).to_html
221
+ )
222
+ klass = resource_class_for_type('text/html')
223
+ @error_resource = klass.new(
224
+ path: '/error.html',
225
+ title: 'Error',
226
+ primary: false,
227
+ input: input)
228
+ add_resource(@error_resource)
229
+ end
230
+
317
231
  def add_feed
318
- @feed_resource = Resource::Feed.new(
319
- output_file: @output_dir / 'feed.xml')
232
+ @feed_resource = Resource::Feed.new(path: '/feed.xml')
320
233
  add_resource(@feed_resource)
321
234
  end
322
235
 
323
236
  def add_sitemap
324
- @sitemap_resource = Resource::Sitemap.new(
325
- output_file: @output_dir / 'sitemap.xml')
237
+ @sitemap_resource = Resource::Sitemap.new(path: '/sitemap.xml')
326
238
  add_resource(@sitemap_resource)
327
239
  end
328
240
 
329
241
  def add_robots
330
- @robots_resource = Resource::Robots.new(
331
- output_file: @output_dir / 'robots.txt')
242
+ @robots_resource = Resource::Robots.new(path: '/robots.txt')
332
243
  add_resource(@robots_resource)
333
244
  end
334
245
 
335
246
  def add_redirects
336
247
  if @redirects
337
248
  @redirects.each do |from, to|
338
- output_file = @output_dir / Path.new(from).relative_to('/')
339
- resource = Resource::Redirect.new(
340
- output_file: output_file,
341
- redirect_uri: to)
249
+ resource = Resource::Redirect.new(path: Path.new(from).add_extension('.redirect').to_s, redirect_uri: to)
342
250
  add_resource(resource)
343
251
  end
344
252
  end
345
253
  end
346
254
 
347
- def add_google_site_verification
348
- resource = Resource::GoogleSiteVerification.new(
349
- output_file: (@output_dir / @google_site_verification).add_extension('.html'),
350
- key: @google_site_verification)
351
- add_resource(resource)
255
+ def check_uri(uri, external: false)
256
+ if uri.relative?
257
+ unless find_resource(uri.path)
258
+ raise Error, "NOT FOUND: #{uri}"
259
+ end
260
+ elsif external
261
+ if uri.scheme.start_with?('http')
262
+ # warn "checking external URI: #{uri}"
263
+ begin
264
+ check_external_uri(uri)
265
+ rescue => e
266
+ raise Error, "external URI: #{uri}: #{e}"
267
+ end
268
+ else
269
+ warn "Don't know how to check URI: #{uri}"
270
+ end
271
+ end
352
272
  end
353
273
 
354
- def add_htpasswd
355
- resource = Resource.new(
356
- input_file: @htpasswd_file,
357
- output_file: @output_dir / '.htpasswd')
358
- add_resource(resource)
274
+ def check_external_uri(uri)
275
+ response = HTTP.timeout(3).get(uri)
276
+ case response.code
277
+ when 200...300
278
+ # ignore
279
+ when 300...400
280
+ redirect_uri = Addressable::URI.parse(response.headers['Location'])
281
+ check_external_uri(uri + redirect_uri)
282
+ when 404
283
+ raise Error, "URI not found: #{uri}"
284
+ when 999
285
+ # ignore bogus LinkedIn status
286
+ else
287
+ raise Error, "Bad status from #{uri}: #{response.inspect}"
288
+ end
359
289
  end
360
290
 
361
291
  end
data/lib/mill.rb CHANGED
@@ -1,28 +1,48 @@
1
1
  require 'addressable'
2
+ require 'hashstruct'
3
+ require 'http'
2
4
  require 'image_size'
3
5
  require 'kramdown'
4
6
  require 'mime/types'
5
7
  require 'nokogiri'
6
8
  require 'path'
7
- require 'pp'
8
9
  require 'RedCloth'
9
- require 'rubypants'
10
+ require 'run-command'
10
11
  require 'sassc'
12
+ require 'set_params'
13
+ require 'simple-builder'
14
+ require 'simple-command-parser'
15
+ require 'simple-configurator'
16
+ require 'simple-printer'
11
17
  require 'time'
12
- require 'web-checker'
18
+ require 'tree'
13
19
 
20
+ class Class
21
+
22
+ def self.subclasses
23
+ constants
24
+ .map { |c| const_get(c) }
25
+ .select { |c| c.kind_of?(Class) }
26
+ end
27
+
28
+ end
29
+
30
+ require 'mill/command'
31
+ require 'mill/config'
14
32
  require 'mill/error'
15
- require 'mill/html_helpers'
16
- require 'mill/navigator'
17
33
  require 'mill/resource'
34
+ require 'mill/resources'
18
35
  require 'mill/resources/blob'
19
36
  require 'mill/resources/feed'
20
- require 'mill/resources/google_site_verification'
21
37
  require 'mill/resources/image'
38
+ require 'mill/resources/markup'
39
+ require 'mill/resources/markdown'
40
+ require 'mill/resources/page'
22
41
  require 'mill/resources/redirect'
23
42
  require 'mill/resources/robots'
24
43
  require 'mill/resources/sitemap'
25
44
  require 'mill/resources/stylesheet'
26
- require 'mill/resources/text'
45
+ require 'mill/resources/textile'
27
46
  require 'mill/site'
28
- require 'mill/version'
47
+
48
+ Path.new(__FILE__).dirname.glob('mill/commands/*.rb').each { |p| require p }
data/mill.gemspec CHANGED
@@ -1,10 +1,6 @@
1
- #encoding: utf-8
2
-
3
- require_relative 'lib/mill/version'
4
-
5
1
  Gem::Specification.new do |s|
6
2
  s.name = 'mill'
7
- s.version = Mill::VERSION
3
+ s.version = '0.18'
8
4
  s.summary = 'A simple but useful static site generator.'
9
5
  s.author = 'John Labovitz'
10
6
  s.email = 'johnl@johnlabovitz.com'
@@ -12,23 +8,32 @@ Gem::Specification.new do |s|
12
8
  Mill provides a simple but useful static site generator.
13
9
  }
14
10
  s.license = 'MIT'
15
- s.homepage = 'http://github.com/jslabovitz/mill'
11
+ s.homepage = 'https://github.com/jslabovitz/mill'
16
12
  s.files = `git ls-files`.split("\n")
17
13
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
14
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
15
  s.require_path = 'lib'
20
16
 
21
- s.add_dependency 'addressable', '~> 2.5'
22
- s.add_dependency 'image_size', '~> 1.5'
23
- s.add_dependency 'kramdown', '~> 1.16'
24
- s.add_dependency 'mime-types', '~> 3.1'
25
- s.add_dependency 'nokogiri', '~> 1.8'
26
- s.add_dependency 'path', '~> 2.0'
17
+ s.add_dependency 'addressable', '~> 2.8'
18
+ s.add_dependency 'hashstruct', '~> 1.6'
19
+ s.add_dependency 'http', '~> 5.3'
20
+ s.add_dependency 'image_size', '~> 3.4'
21
+ s.add_dependency 'kramdown', '~> 2.5'
22
+ s.add_dependency 'mime-types', '~> 3.7'
23
+ s.add_dependency 'nokogiri', '~> 1.18'
24
+ s.add_dependency 'path', '~> 2.1'
27
25
  s.add_dependency 'RedCloth', '~> 4.3'
28
- s.add_dependency 'rubypants', '~> 0.6'
29
- s.add_dependency 'sassc', '~> 2.0'
30
- s.add_dependency 'web-checker', '~> 0'
26
+ s.add_dependency 'rubypants', '~> 0.7'
27
+ s.add_dependency 'rubytree', '~> 2.1'
28
+ s.add_dependency 'sassc', '~> 2.4'
29
+ s.add_dependency 'set_params', '~> 0.3'
30
+ s.add_dependency 'simple-builder', '~> 0.4'
31
+ s.add_dependency 'simple-command-parser', '~> 1.2'
32
+ s.add_dependency 'simple-configurator', '~> 0.2'
33
+ s.add_dependency 'simple-printer', '~> 0.4'
31
34
 
32
- s.add_development_dependency 'rake', '~> 0'
33
- s.add_development_dependency 'rubygems-tasks', '~> 0.0'
35
+ s.add_development_dependency 'minitest', '~> 5.26'
36
+ s.add_development_dependency 'minitest-power_assert', '~> 0.3'
37
+ s.add_development_dependency 'rake', '~> 13.3'
38
+ s.add_development_dependency 'simple-rake-tasks', '~> 0.1'
34
39
  end
data/test/content/a.md ADDED
@@ -0,0 +1,3 @@
1
+ Title: a
2
+
3
+ This is a.
@@ -0,0 +1,3 @@
1
+ Title: ba
2
+
3
+ This is ba.
@@ -0,0 +1,3 @@
1
+ Title: bb
2
+
3
+ This is bb.
@@ -0,0 +1,3 @@
1
+ Title: b index
2
+
3
+ This is index of b.
data/test/content/c.md ADDED
@@ -0,0 +1,4 @@
1
+ Title: c
2
+ Primary: false
3
+
4
+ This is c.