mill 0.11 → 0.16

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 552fff29a5bcd1a558ba23332357186141369ddb3077452a0b0d8a7514df257a
4
- data.tar.gz: 96b5ce3171c004bcf807b3d8b6185bd83b3c8d120f5e896cf046ba8dca70a38f
3
+ metadata.gz: 5accfe1e5067386b3de4898faceb6ea201c6bc30097da779c38ef343e0aad18c
4
+ data.tar.gz: 5861a090880607573153929c75f0475fb258467676b2a4084514e8b368028bb6
5
5
  SHA512:
6
- metadata.gz: a8fb52dc75caeee17ba0fe74d1182b4a64c9dd6edaca7891360019e70facb3cac35cfdf46ad6a6c81708ef65fce775969b12d404c5d577ca922989a2b0155c01
7
- data.tar.gz: 12423dfe0681de5e5aacf90cb97167b44193e332ed7f8a62b1b4cbbb7426fe4d4ce3f5cde9784c414683cfb9b1096357bffd74bccb1dcaf1a2b4457bcd07ee5a
6
+ metadata.gz: 1c1e0a63042509e67a028e2e50b2f61fa92560ee16bb77370ca1ca82d1f75ebbd7054b9ba8b2408aff32e83a44c3e5f9cc2600316e5dd22c8a47ef7d26cee932
7
+ data.tar.gz: 7dc21c2b4181768be5150d1e51ef6ea9b16aba0a33c8536dd9609e72b458913e2fa79ee460d9c50c204dc6a0da733587bd4807005a16ca2acc4e5806b33d168d
data/.gitignore CHANGED
@@ -1 +1,11 @@
1
- *.gem
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ /test/output
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'path', github: 'eregon/path'
6
+ gem 'rubytree', github: 'evolve75/RubyTree'
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
- require 'rubygems/tasks'
2
- Gem::Tasks.new
1
+ require 'bundler/gem_tasks'
2
+ Bundler.require
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/*test.rb']
7
+ end
8
+
9
+ task :default => :test
data/TODO.txt CHANGED
@@ -1,6 +1,10 @@
1
+ - remove textile/pre processors from Resource::Text
2
+ - streamline to allow domain-specific subclassing if needed
3
+
1
4
  - initialize site by setting ivars directly, not by passing params to super's initialize()
2
5
 
3
6
  - create alternate sites (beta, final, etc.) by subclassing site, and changing @output or @location
7
+ - allow CLI option to specify site
4
8
 
5
9
  - rework resource URI usage
6
10
  - 'uri' attribute should be canonical
@@ -41,8 +45,6 @@
41
45
  - sidebars
42
46
  - strings (existing String extensions)
43
47
 
44
- - create bin/mill tool to replace Rake
45
-
46
48
  - split Resource#date into Resource#published & Resource#updated
47
49
  + add <published> element to feed
48
50
  + #published should be stated date (e.g., from header)
@@ -56,6 +58,4 @@
56
58
 
57
59
  - save compressed versions of files
58
60
  - write compressed versions along with non-compressed
59
- - serve compressed versions if asked by client
60
-
61
- - add MailChimp signup form generator to HTMLHelpers
61
+ - serve compressed versions if asked by client
data/bin/mill CHANGED
@@ -20,8 +20,8 @@ begin
20
20
  $site.snapshot
21
21
  when 'upload'
22
22
  $site.upload
23
- when 'output-dir'
24
- puts $site.output_dir
23
+ when 'show'
24
+ puts $site.send(ARGV.shift)
25
25
  else
26
26
  raise "Unknown command: #{command.inspect}"
27
27
  end
@@ -5,10 +5,12 @@ require 'mime/types'
5
5
  require 'nokogiri'
6
6
  require 'path'
7
7
  require 'pp'
8
+ # require 'pry' rescue nil
8
9
  require 'RedCloth'
9
10
  require 'rubypants'
10
11
  require 'sassc'
11
12
  require 'time'
13
+ require 'tree'
12
14
  require 'web-checker'
13
15
 
14
16
  require 'mill/error'
@@ -104,13 +104,19 @@ module HTMLHelpers
104
104
  nil => RubyPants,
105
105
  smart_quotes: RubyPants,
106
106
  markdown: Kramdown::Document,
107
- textile: RedCloth,
107
+ textile: [RedCloth, :no_span_caps],
108
108
  pre: PreText,
109
109
  }
110
110
 
111
111
  def to_html(options={})
112
- converter = Converters[options[:mode]] or raise "Unknown to_html mode: #{options[:mode].inspect}"
113
- html = Nokogiri::HTML::DocumentFragment.parse(converter.new(self).to_html)
112
+ converter_class = Converters[options[:mode]] or raise "Unknown to_html mode: #{options[:mode].inspect}"
113
+ if converter_class.kind_of?(Array)
114
+ converter_class, *converter_options = *converter_class
115
+ converter = converter_class.new(self, converter_options)
116
+ else
117
+ converter = converter_class.new(self)
118
+ end
119
+ html = Nokogiri::HTML::DocumentFragment.parse(converter.to_html)
114
120
  if !options[:multiline] && (p_elem = html.at_xpath('p'))
115
121
  html = p_elem.children.to_html
116
122
  end
@@ -6,10 +6,12 @@ module Mill
6
6
 
7
7
  attr_accessor :input_file
8
8
  attr_accessor :output_file
9
+ attr_accessor :path
9
10
  attr_accessor :date
10
11
  attr_accessor :public
11
12
  attr_accessor :content
12
13
  attr_accessor :site
14
+ attr_accessor :node
13
15
 
14
16
  def initialize(input_file: nil,
15
17
  output_file: nil,
@@ -23,7 +25,10 @@ module Mill
23
25
  else
24
26
  @date = DateTime.now
25
27
  end
26
- @output_file = Path.new(output_file) if output_file
28
+ if output_file
29
+ @output_file = Path.new(output_file)
30
+ @path = '/' + @output_file.relative_to(site.output_dir).to_s
31
+ end
27
32
  self.date = date if date
28
33
  self.public = public
29
34
  @content = content
@@ -57,39 +62,47 @@ module Mill
57
62
  end
58
63
 
59
64
  def public?
60
- @public
65
+ @public == true
66
+ end
67
+
68
+ def text?
69
+ kind_of?(Resource::Text) && public?
70
+ end
71
+
72
+ def redirect?
73
+ kind_of?(Resource::Redirect)
61
74
  end
62
75
 
63
76
  def inspect
64
- "<%p> input_file: %p, output_file: %p, date: %s, public: %p, content: <%p>" % [
77
+ "<%p> input_file: %p, output_file: %p, path: %s, date: %s, public: %p, content: <%p>, parent: %p, siblings: %p, children: %p" % [
65
78
  self.class,
66
79
  @input_file ? @input_file.relative_to(@site.input_dir).to_s : nil,
67
80
  @output_file ? @output_file.relative_to(@site.output_dir).to_s : nil,
81
+ @path,
68
82
  @date.to_s,
69
83
  @public,
70
- @content && @content.class,
84
+ @content&.class,
85
+ parent&.path,
86
+ siblings.map(&:path),
87
+ children.map(&:path),
71
88
  ]
72
89
  end
73
90
 
74
- def find_sibling_resources(klass=nil)
75
- # parent_uri = parent_uri
76
- @site.resources.select do |resource|
77
- resource != self &&
78
- (klass.nil? || resource.kind_of?(klass)) &&
79
- resource.parent_uri == parent_uri
80
- end
91
+ def parent
92
+ @node.parent&.content
81
93
  end
82
94
 
83
- def uri
84
- raise Error, "#{@input_file}: No output file defined for #{self.class}" unless @output_file
85
- path = '/' + @output_file.relative_to(@site.output_dir).to_s
86
- path.sub!(%r{/index\.html$}, '/')
87
- path.sub!(%r{\.html$}, '') if @site.shorten_uris
88
- Addressable::URI.encode(path, Addressable::URI)
95
+ def siblings
96
+ @node.siblings.map(&:content).compact
89
97
  end
90
98
 
91
- def parent_uri
92
- uri + '.'
99
+ def children
100
+ @node.children.map(&:content).compact
101
+ end
102
+
103
+ def uri
104
+ raise Error, "#{@input_file}: No path defined for #{self.class}" unless @path
105
+ Addressable::URI.encode(@path, Addressable::URI)
93
106
  end
94
107
 
95
108
  def absolute_uri
@@ -119,14 +132,14 @@ module Mill
119
132
  def save
120
133
  @output_file.dirname.mkpath
121
134
  if (content = final_content)
122
- # ;;warn "#{uri}: writing #{@input_file} to #{@output_file}"
135
+ # ;;warn "#{path}: writing #{@input_file} to #{@output_file}"
123
136
  @output_file.write(content.to_s)
124
137
  @output_file.utime(@date.to_time, @date.to_time)
125
138
  elsif @input_file
126
- # ;;warn "#{uri}: copying #{@input_file} to #{@output_file}"
139
+ # ;;warn "#{path}: copying #{@input_file} to #{@output_file}"
127
140
  @input_file.copy(@output_file)
128
141
  else
129
- raise Error, "Can't build resource without content or input file: #{uri}"
142
+ raise Error, "Can't build resource without content or input file: #{path}"
130
143
  end
131
144
  end
132
145
 
@@ -1,3 +1,4 @@
1
+
1
2
  module Mill
2
3
 
3
4
  class Resource
@@ -15,19 +16,29 @@ module Mill
15
16
  attr_accessor :title
16
17
  attr_accessor :summary
17
18
  attr_accessor :author
19
+ attr_accessor :type
18
20
 
19
- def initialize(title: nil, summary: nil, author: nil, public: true, **args)
21
+ def initialize(title: nil, summary: nil, author: nil, public: true, output_file: nil, **args)
20
22
  @title = title
21
23
  @summary = summary
22
24
  @author = author
23
- super(public: public, **args)
25
+ @type = nil
26
+ super(
27
+ public: public,
28
+ output_file: output_file&.replace_extension('.html'),
29
+ **args)
30
+ if @path
31
+ @path.sub!(%r{\.html$}, '') if @site&.shorten_uris
32
+ @path.sub!(%r{(.*)index$}, '\1')
33
+ end
24
34
  end
25
35
 
26
36
  def inspect
27
- super + ", title: %p, summary: %p, author: %p" % [
37
+ super + ", title: %p, summary: %p, author: %p, type: %p" % [
28
38
  @title,
29
39
  @summary,
30
40
  @author,
41
+ @type,
31
42
  ]
32
43
  end
33
44
 
@@ -35,7 +46,7 @@ module Mill
35
46
  super
36
47
  if @input_file
37
48
  @content = @input_file.read
38
- mode = case @input_file.extname.downcase
49
+ @type = case @input_file.extname.downcase
39
50
  when '.md', '.mdown', '.markdown'
40
51
  :markdown
41
52
  when '.textile'
@@ -47,10 +58,10 @@ module Mill
47
58
  else
48
59
  raise "Unknown text type: #{@input_file}"
49
60
  end
50
- if mode != :html
61
+ if @type != :html
51
62
  parse_text_header
52
- @content = (@content || '').to_html(mode: mode, multiline: true)
53
- @output_file = @output_file.replace_extension('.html')
63
+ @content = (@content || '').to_html(mode: @type, multiline: true)
64
+ @type = :html
54
65
  end
55
66
  begin
56
67
  @content = parse_html(@content)
@@ -66,7 +77,7 @@ module Mill
66
77
  if (title_elem = @content.at_xpath('/html/head/title'))
67
78
  @title = title_elem.text
68
79
  else
69
- @title = uri.to_s
80
+ @title = @path
70
81
  end
71
82
  end
72
83
  @content.xpath('/html/head/meta[@name]').each do |meta|
@@ -78,7 +89,7 @@ module Mill
78
89
  if @content.split(/\n/, 2).first =~ /^\w+:\s+/
79
90
  header, @content = @content.split(/\n\n/, 2)
80
91
  header.split(/\n/).map do |line|
81
- key, value = line.strip.split(/:\s+/, 2)
92
+ key, value = line.strip.split(/:\s*/, 2)
82
93
  key = key.gsub('-', '_').downcase.to_sym
83
94
  send("#{key}=", value)
84
95
  end
@@ -86,7 +97,7 @@ module Mill
86
97
  end
87
98
 
88
99
  def final_content
89
- html_document(@site.html_version) do |doc|
100
+ html_document(@site&.html_version || :html5) do |doc|
90
101
  doc.html(lang: 'en') do |html|
91
102
  html.parent << head
92
103
  html.parent << body
@@ -168,7 +179,7 @@ module Mill
168
179
  self_uri.scheme = 'http'
169
180
  link_uri.scheme = 'http'
170
181
  attribute.value = self_uri.route_to(link_uri)
171
- # ;;warn "[#{uri}] shortened link #{elem.name}/@#{attribute.name}: #{link_uri} => #{attribute.value}"
182
+ # ;;warn "[#{path}] shortened link #{elem.name}/@#{attribute.name}: #{link_uri} => #{attribute.value}"
172
183
  end
173
184
  end
174
185
  end
@@ -195,7 +206,7 @@ module Mill
195
206
  body_elem.children
196
207
  end
197
208
  else
198
- warn "Warning: Resource #{uri} (#{self.class}) has no content"
209
+ warn "Warning: Resource #{path} (#{self.class}) has no content"
199
210
  nil
200
211
  end
201
212
  end
@@ -64,8 +64,8 @@ module Mill
64
64
  @google_site_verification = google_site_verification
65
65
  @redirects = redirects
66
66
 
67
- @resources = []
68
- @resources_by_uri = {}
67
+ @resources = {}
68
+ @resources_tree = Tree::TreeNode.new('')
69
69
  build_file_types
70
70
  end
71
71
 
@@ -79,35 +79,20 @@ module Mill
79
79
  end
80
80
 
81
81
  def add_resource(resource)
82
- resource.site = self
83
- @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
- end
92
-
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]
82
+ raise "Must assign resource to site" unless resource.site
83
+ @resources[resource.path] = resource
84
+ node = @resources_tree
85
+ resource.path.split('/').reject(&:empty?).each do |component|
86
+ node = node[component] || (node << Tree::TreeNode.new(component))
99
87
  end
100
- resource
88
+ resource.node = node
89
+ node.content = resource
90
+ # ;;warn "added #{resource} as #{resource.path}"
101
91
  end
102
92
 
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
- )
93
+ def find_resource(path)
94
+ path = path.path if path.kind_of?(Addressable::URI)
95
+ @resources[path] || @resources[path + '/']
111
96
  end
112
97
 
113
98
  def home_resource
@@ -135,20 +120,30 @@ module Mill
135
120
  @site_email
136
121
  end
137
122
 
123
+ def select_resources(selector=nil, &block)
124
+ if block_given?
125
+ @resources.values.select(&block)
126
+ elsif selector.kind_of?(Class)
127
+ @resources.values.select { |r| r.kind_of?(selector) }
128
+ else
129
+ @resources.values.select(selector)
130
+ end
131
+ end
132
+
138
133
  def feed_resources
139
134
  public_resources.sort_by(&:date)
140
135
  end
141
136
 
142
137
  def public_resources
143
- @resources.select(&:public)
138
+ select_resources(&:public?)
144
139
  end
145
140
 
146
- def private_resources
147
- @resources.select { |r| r.kind_of?(Resource::Text) && !r.public }
141
+ def redirect_resources
142
+ select_resources(&:redirect?)
148
143
  end
149
144
 
150
- def redirect_resources
151
- @resources.select { |r| r.kind_of?(Resource::Redirect) }
145
+ def text_resources
146
+ select_resources(&:text?)
152
147
  end
153
148
 
154
149
  def make
@@ -156,35 +151,67 @@ module Mill
156
151
  save
157
152
  end
158
153
 
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
- }
154
+ def print_tree(node=nil, level=0)
155
+ node ||= @resources_tree
156
+ if node.is_root?
157
+ print '*'
158
+ else
159
+ print "\t" * level
160
+ end
161
+ print " #{node.name.inspect}"
162
+ print " <#{node.content&.path}>"
163
+ print " (#{node.children.length} children)" if node.has_children?
164
+ puts
165
+ node.children { |child| print_tree(child, level + 1) }
166
+ end
167
+
168
+ ListKeys = {
169
+ path: :to_s,
170
+ input_file: :to_s,
171
+ output_file: :to_s,
172
+ date: :to_s,
173
+ public: :to_s,
174
+ class: :to_s,
175
+ content: proc { |r| r.content ? ('%s (%dKB)' % [r.content.class, (r.content.to_s.length / 1024.0).ceil]) : nil },
176
+ parent: proc { |r| r.parent&.path },
177
+ siblings: proc { |r| r.siblings.map(&:path) },
178
+ children: proc { |r| r.children.map(&:path) },
179
+ }
168
180
 
181
+ def list
169
182
  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
- ]
183
+ width = ListKeys.keys.map(&:length).max
184
+ select_resources.each do |resource|
185
+ ListKeys.each do |key, converter|
186
+ value = resource.send(key)
187
+ value = case converter
188
+ when nil
189
+ value
190
+ when Symbol
191
+ value.send(converter)
192
+ when Proc
193
+ converter.call(resource)
194
+ else
195
+ raise
178
196
  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
197
+ print '%*s: ' % [width, key]
198
+ case value
199
+ when Array
200
+ if value.empty?
201
+ puts '-'
202
+ else
203
+ value.each_with_index do |v, i|
204
+ print '%*s ' % [width, ''] if i > 0
205
+ puts (v.nil? ? '-' : v)
206
+ end
207
+ end
208
+ else
209
+ puts (value.nil? ? '-' : value)
210
+ end
211
+ end
212
+ puts
187
213
  end
214
+ puts
188
215
  end
189
216
 
190
217
  def build
@@ -205,14 +232,14 @@ module Mill
205
232
 
206
233
  def load_resources
207
234
  on_each_resource do |resource|
208
- # ;;warn "#{resource.uri}: loading"
235
+ # ;;warn "#{resource.path}: loading"
209
236
  resource.load
210
237
  end
211
238
  end
212
239
 
213
240
  def build_resources
214
241
  on_each_resource do |resource|
215
- # ;;warn "#{resource.uri}: building"
242
+ # ;;warn "#{resource.path}: building"
216
243
  resource.build
217
244
  end
218
245
  end
@@ -221,7 +248,7 @@ module Mill
221
248
  clean
222
249
  @output_dir.mkpath
223
250
  on_each_resource do |resource|
224
- # ;;warn "#{resource.uri}: saving"
251
+ # ;;warn "#{resource.path}: saving"
225
252
  resource.save
226
253
  end
227
254
  end
@@ -241,6 +268,8 @@ module Mill
241
268
 
242
269
  def snapshot
243
270
  @output_dir.chdir do
271
+ system('git',
272
+ 'init') unless Path.new('.git').exist?
244
273
  system('git',
245
274
  'add',
246
275
  '.')
@@ -265,6 +294,7 @@ module Mill
265
294
  '--progress',
266
295
  '--verbose',
267
296
  '--archive',
297
+ # '--append-verify',
268
298
  '--exclude=.git',
269
299
  '--delete-after',
270
300
  @output_dir.to_s,
@@ -272,17 +302,11 @@ module Mill
272
302
  end
273
303
 
274
304
  def on_each_resource(&block)
275
- @resources.each do |resource|
276
- old_uri = resource.uri.dup
305
+ @resources.values.each do |resource|
277
306
  begin
278
307
  yield(resource)
279
308
  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
309
+ raise e, "#{resource.input_file || '-'} (#{resource.path}): #{e}"
286
310
  end
287
311
  end
288
312
  end
@@ -299,7 +323,7 @@ module Mill
299
323
  end
300
324
 
301
325
  def add_files
302
- raise Error, "Input path not found: #{@input_dir}" unless @input_dir.exist?
326
+ raise Error, "Input directory not found: #{@input_dir}" unless @input_dir.exist?
303
327
  @input_dir.find do |input_file|
304
328
  if input_file.basename.to_s[0] == '.'
305
329
  Find.prune
@@ -308,7 +332,8 @@ module Mill
308
332
  else (klass = resource_class_for_file(input_file))
309
333
  resource = klass.new(
310
334
  input_file: input_file,
311
- output_file: @output_dir / input_file.relative_to(@input_dir))
335
+ output_file: @output_dir / input_file.relative_to(@input_dir),
336
+ site: self)
312
337
  add_resource(resource)
313
338
  end
314
339
  end
@@ -316,19 +341,22 @@ module Mill
316
341
 
317
342
  def add_feed
318
343
  @feed_resource = Resource::Feed.new(
319
- output_file: @output_dir / 'feed.xml')
344
+ output_file: @output_dir / 'feed.xml',
345
+ site: self)
320
346
  add_resource(@feed_resource)
321
347
  end
322
348
 
323
349
  def add_sitemap
324
350
  @sitemap_resource = Resource::Sitemap.new(
325
- output_file: @output_dir / 'sitemap.xml')
351
+ output_file: @output_dir / 'sitemap.xml',
352
+ site: self)
326
353
  add_resource(@sitemap_resource)
327
354
  end
328
355
 
329
356
  def add_robots
330
357
  @robots_resource = Resource::Robots.new(
331
- output_file: @output_dir / 'robots.txt')
358
+ output_file: @output_dir / 'robots.txt',
359
+ site: self)
332
360
  add_resource(@robots_resource)
333
361
  end
334
362
 
@@ -338,7 +366,8 @@ module Mill
338
366
  output_file = @output_dir / Path.new(from).relative_to('/')
339
367
  resource = Resource::Redirect.new(
340
368
  output_file: output_file,
341
- redirect_uri: to)
369
+ redirect_uri: to,
370
+ site: self)
342
371
  add_resource(resource)
343
372
  end
344
373
  end
@@ -347,14 +376,16 @@ module Mill
347
376
  def add_google_site_verification
348
377
  resource = Resource::GoogleSiteVerification.new(
349
378
  output_file: (@output_dir / @google_site_verification).add_extension('.html'),
350
- key: @google_site_verification)
379
+ key: @google_site_verification,
380
+ site: self)
351
381
  add_resource(resource)
352
382
  end
353
383
 
354
384
  def add_htpasswd
355
385
  resource = Resource.new(
356
386
  input_file: @htpasswd_file,
357
- output_file: @output_dir / '.htpasswd')
387
+ output_file: @output_dir / '.htpasswd',
388
+ site: self)
358
389
  add_resource(resource)
359
390
  end
360
391
 
@@ -1,5 +1,5 @@
1
1
  module Mill
2
2
 
3
- VERSION = '0.11'
3
+ VERSION = '0.16'
4
4
 
5
5
  end
@@ -18,17 +18,22 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
19
  s.require_path = 'lib'
20
20
 
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'
21
+ s.add_dependency 'addressable', '~> 2.7'
22
+ s.add_dependency 'image_size', '~> 2.1'
23
+ s.add_dependency 'kramdown', '~> 2.3'
24
+ s.add_dependency 'mime-types', '~> 3.3'
25
+ s.add_dependency 'nokogiri', '~> 1.10'
26
26
  s.add_dependency 'path', '~> 2.0'
27
27
  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'
28
+ s.add_dependency 'rubypants', '~> 0.7'
29
+ s.add_dependency 'rubytree', '~> 1.0'
30
+ s.add_dependency 'sassc', '~> 2.4'
31
+ s.add_dependency 'web-checker', '~> 0.4'
31
32
 
32
- s.add_development_dependency 'rake', '~> 0'
33
- s.add_development_dependency 'rubygems-tasks', '~> 0.0'
33
+ s.add_development_dependency 'bundler', '~> 2.2'
34
+ s.add_development_dependency 'minitest', '~> 5.14'
35
+ s.add_development_dependency 'minitest-power_assert', '~> 0.3'
36
+ s.add_development_dependency 'pry', '~> 0.13'
37
+ s.add_development_dependency 'rake', '~> 13.0'
38
+ s.add_development_dependency 'rubygems-tasks', '~> 0.2'
34
39
  end
@@ -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.
@@ -0,0 +1,3 @@
1
+ Title: index
2
+
3
+ This is index.
@@ -0,0 +1,56 @@
1
+ $VERBOSE = false
2
+
3
+ require 'minitest/autorun'
4
+ require 'minitest/power_assert'
5
+
6
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
7
+ require 'mill'
8
+
9
+ module Mill
10
+
11
+ class Test < Minitest::Test
12
+
13
+ def setup
14
+ @site = Site.new(
15
+ input_dir: 'test/content',
16
+ output_dir: 'test/output',
17
+ site_title: 'Test',
18
+ site_uri: 'http://test.test',
19
+ html_version: :html5,
20
+ )
21
+ @site.make
22
+ # ;;@site.print_tree
23
+ # ;;@site.list
24
+ # ;;binding.pry
25
+ @root = @site.find_resource('/') or raise
26
+ @a = @site.find_resource('/a') or raise
27
+ @b = @site.find_resource('/b') or raise
28
+ @ba = @site.find_resource('/b/ba') or raise
29
+ @bb = @site.find_resource('/b/bb') or raise
30
+ end
31
+
32
+ def test_has_index
33
+ assert { @root }
34
+ end
35
+
36
+ def test_children
37
+ assert { @root.children == [@a, @b] }
38
+ assert { @a.children.empty? }
39
+ end
40
+
41
+ def test_parent
42
+ assert { @a.parent == @root }
43
+ assert { @b.parent == @root }
44
+ assert { @ba.parent == @b }
45
+ assert { @bb.parent == @b }
46
+ end
47
+
48
+ def test_siblings
49
+ assert { @root.siblings.empty? }
50
+ assert { @a.siblings == [@b] }
51
+ assert { @ba.siblings == [@bb] }
52
+ end
53
+
54
+ end
55
+
56
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mill
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.11'
4
+ version: '0.16'
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Labovitz
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-28 00:00:00.000000000 Z
11
+ date: 2020-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -16,70 +16,70 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.5'
19
+ version: '2.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.5'
26
+ version: '2.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: image_size
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.5'
33
+ version: '2.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.5'
40
+ version: '2.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: kramdown
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.16'
47
+ version: '2.3'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.16'
54
+ version: '2.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mime-types
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.1'
61
+ version: '3.3'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.1'
68
+ version: '3.3'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: nokogiri
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.8'
75
+ version: '1.10'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.8'
82
+ version: '1.10'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: path
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,70 +114,140 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.6'
117
+ version: '0.7'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.6'
124
+ version: '0.7'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubytree
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: sassc
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
- version: '2.0'
145
+ version: '2.4'
132
146
  type: :runtime
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
- version: '2.0'
152
+ version: '2.4'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: web-checker
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
157
  - - "~>"
144
158
  - !ruby/object:Gem::Version
145
- version: '0'
159
+ version: '0.4'
146
160
  type: :runtime
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
- version: '0'
166
+ version: '0.4'
167
+ - !ruby/object:Gem::Dependency
168
+ name: bundler
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.2'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.2'
181
+ - !ruby/object:Gem::Dependency
182
+ name: minitest
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '5.14'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '5.14'
195
+ - !ruby/object:Gem::Dependency
196
+ name: minitest-power_assert
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '0.3'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '0.3'
209
+ - !ruby/object:Gem::Dependency
210
+ name: pry
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '0.13'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '0.13'
153
223
  - !ruby/object:Gem::Dependency
154
224
  name: rake
155
225
  requirement: !ruby/object:Gem::Requirement
156
226
  requirements:
157
227
  - - "~>"
158
228
  - !ruby/object:Gem::Version
159
- version: '0'
229
+ version: '13.0'
160
230
  type: :development
161
231
  prerelease: false
162
232
  version_requirements: !ruby/object:Gem::Requirement
163
233
  requirements:
164
234
  - - "~>"
165
235
  - !ruby/object:Gem::Version
166
- version: '0'
236
+ version: '13.0'
167
237
  - !ruby/object:Gem::Dependency
168
238
  name: rubygems-tasks
169
239
  requirement: !ruby/object:Gem::Requirement
170
240
  requirements:
171
241
  - - "~>"
172
242
  - !ruby/object:Gem::Version
173
- version: '0.0'
243
+ version: '0.2'
174
244
  type: :development
175
245
  prerelease: false
176
246
  version_requirements: !ruby/object:Gem::Requirement
177
247
  requirements:
178
248
  - - "~>"
179
249
  - !ruby/object:Gem::Version
180
- version: '0.0'
250
+ version: '0.2'
181
251
  description: "\n Mill provides a simple but useful static site generator.\n "
182
252
  email: johnl@johnlabovitz.com
183
253
  executables:
@@ -186,6 +256,7 @@ extensions: []
186
256
  extra_rdoc_files: []
187
257
  files:
188
258
  - ".gitignore"
259
+ - Gemfile
189
260
  - LICENSE
190
261
  - README.md
191
262
  - Rakefile
@@ -209,11 +280,17 @@ files:
209
280
  - lib/mill/site.rb
210
281
  - lib/mill/version.rb
211
282
  - mill.gemspec
283
+ - test/content/a.md
284
+ - test/content/b/ba.md
285
+ - test/content/b/bb.md
286
+ - test/content/b/index.md
287
+ - test/content/index.md
288
+ - test/test.rb
212
289
  homepage: http://github.com/jslabovitz/mill
213
290
  licenses:
214
291
  - MIT
215
292
  metadata: {}
216
- post_install_message:
293
+ post_install_message:
217
294
  rdoc_options: []
218
295
  require_paths:
219
296
  - lib
@@ -228,9 +305,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
305
  - !ruby/object:Gem::Version
229
306
  version: '0'
230
307
  requirements: []
231
- rubyforge_project:
232
- rubygems_version: 2.7.7
233
- signing_key:
308
+ rubygems_version: 3.2.3
309
+ signing_key:
234
310
  specification_version: 4
235
311
  summary: A simple but useful static site generator.
236
- test_files: []
312
+ test_files:
313
+ - test/content/a.md
314
+ - test/content/b/ba.md
315
+ - test/content/b/bb.md
316
+ - test/content/b/index.md
317
+ - test/content/index.md
318
+ - test/test.rb