mill 0.1 → 0.3
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 +5 -5
- data/Gemfile +0 -2
- data/TODO.txt +48 -25
- data/bin/mill +19 -0
- data/lib/mill.rb +7 -316
- data/lib/mill/error.rb +7 -0
- data/lib/mill/html_helpers.rb +57 -67
- data/lib/mill/navigator.rb +26 -50
- data/lib/mill/resource.rb +78 -59
- data/lib/mill/resources/dir.rb +31 -0
- data/lib/mill/resources/feed.rb +13 -22
- data/lib/mill/resources/google_site_verification.rb +24 -0
- data/lib/mill/resources/image.rb +12 -5
- data/lib/mill/resources/other.rb +29 -0
- data/lib/mill/resources/redirect.rb +7 -13
- data/lib/mill/resources/robots.rb +6 -9
- data/lib/mill/resources/sitemap.rb +3 -7
- data/lib/mill/resources/stylesheet.rb +27 -0
- data/lib/mill/resources/text.rb +139 -59
- data/lib/mill/site.rb +304 -0
- data/lib/mill/version.rb +2 -2
- data/mill.gemspec +1 -3
- data/test/Gemfile +7 -0
- data/test/Rakefile +7 -0
- data/test/content/a.md +3 -0
- data/test/content/b/index.md +3 -0
- data/test/content/index.md +3 -0
- metadata +24 -37
- data/lib/mill/file_types.rb +0 -30
- data/lib/mill/resources/generic.rb +0 -15
- data/lib/mill/tasks.rake +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1f8000209c86dddb14cc2a494f51ac7e6de3b88612c17e82347921d99c279f51
|
4
|
+
data.tar.gz: a3e076dc13fce8f7002b056639792114e876f70ab69266df761c5ae576b2eda6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e939321da85e85ba819a6f32808e8d027eedca5e9200087f2560fbaefd8bc0f4cef5459622a91a93ce51d1597fb040730f0abfc7fb0a09c074af31606c59a030
|
7
|
+
data.tar.gz: 4897e121dc46248eaef16b998c60a76ba2a1e1c0a7d590e733986e66f9622af2001c2f0015d7f230cadefadbdcdbff301b4a1c2a495266781f930fd0cbf21429
|
data/Gemfile
CHANGED
data/TODO.txt
CHANGED
@@ -1,38 +1,61 @@
|
|
1
|
-
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
- initialize site by setting ivars directly, not by passing params to super's initialize()
|
2
|
+
|
3
|
+
- create alternate sites (beta, final, etc.) by subclassing site, and changing @output or @location
|
4
|
+
|
5
|
+
- rework resource URI usage
|
6
|
+
- 'uri' attribute should be canonical
|
7
|
+
- 'output_file' should be derived from @site.output_dir + uri
|
8
|
+
- URIs should be fully qualified
|
9
|
+
- start with '/'
|
10
|
+
- have extension according to file type
|
11
|
+
- referencing URIs should follow server rules (e.g., / -> /index.html)
|
12
|
+
- #shorten_uris should only apply to writing final files
|
13
|
+
|
14
|
+
- combine @input_file & @content?
|
15
|
+
- if @content.kind_of?(Path): copy
|
16
|
+
- else: write as string
|
17
|
+
|
18
|
+
- rename Resource #load to #import
|
19
|
+
- uses path argument instead of @input_file
|
20
|
+
- sets @content to path
|
21
|
+
- sets @date to mtime of path
|
22
|
+
- subclasses should:
|
23
|
+
- call super
|
24
|
+
- subclasses may:
|
25
|
+
- assigned @content
|
26
|
+
- change URI
|
27
|
+
|
28
|
+
- rename Resource #build to #process
|
29
|
+
|
30
|
+
- formalize widget creation & access
|
31
|
+
- any object that responds to #to_html
|
32
|
+
- doesn't have to be specific class (e.g., Mill::Widget)
|
33
|
+
- object that is used across site
|
34
|
+
- possibly with different states or parameters (eg, navigation)
|
35
|
+
- built from current html_fragment use
|
36
|
+
- eg:
|
37
|
+
- navigation
|
38
|
+
- buy buttons
|
39
|
+
- Google Analytics bug
|
40
|
+
- link to resource (<a ...>)
|
41
|
+
- sidebars
|
42
|
+
- strings (existing String extensions)
|
43
|
+
|
44
|
+
- create bin/mill tool to replace Rake
|
5
45
|
|
6
46
|
- split Resource#date into Resource#published & Resource#updated
|
7
47
|
+ add <published> element to feed
|
8
48
|
+ #published should be stated date (e.g., from header)
|
9
49
|
+ #updated should be mtime of source file
|
10
50
|
|
11
|
-
- refactor MIME type usage
|
12
|
-
+ allow specified type as regexp or glob (use File.fnmatch?)
|
13
|
-
+ convert to MIME::Type object(s)
|
14
|
-
|
15
51
|
- make Navigator into more generic Collection
|
16
52
|
+ include Enumerable
|
17
53
|
|
18
54
|
- make Resource::External for external links?
|
19
55
|
+ add on import of HTML (by examining href/src/etc attributes)
|
20
56
|
|
21
|
-
-
|
22
|
-
|
23
|
-
|
24
|
-
+ A #convert_uris method should convert all references to proper type.
|
25
|
-
|
26
|
-
- Compress/minify Javascript, CSS, and HTML
|
27
|
-
+ https://remino.net/rails-html-css-js-gzip-compression/
|
28
|
-
+ http://sass-lang.com/documentation/file.SASS_REFERENCE.html#_16
|
29
|
-
+ JS: https://github.com/lautis/uglifier
|
30
|
-
+ HTML: https://github.com/paolochiodi/htmlcompressor
|
31
|
-
+ CSS: https://github.com/matthiassiegel/cssminify
|
32
|
-
|
33
|
-
- Write compressed versions along with non-compressed
|
34
|
-
+ Modify SimpleServer to use compressed versions if asked by client
|
35
|
-
|
36
|
-
- Add MailChimp signup form generator to HTMLHelpers.
|
57
|
+
- save compressed versions of files
|
58
|
+
- write compressed versions along with non-compressed
|
59
|
+
- serve compressed versions if asked by client
|
37
60
|
|
38
|
-
-
|
61
|
+
- add MailChimp signup form generator to HTMLHelpers
|
data/bin/mill
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mill'
|
4
|
+
|
5
|
+
load Path.pwd / 'code' / 'site.rb'
|
6
|
+
|
7
|
+
begin
|
8
|
+
case ARGV.shift
|
9
|
+
when nil, 'make'
|
10
|
+
$site.make
|
11
|
+
when 'list'
|
12
|
+
$site.list
|
13
|
+
else
|
14
|
+
raise "Unknown command: #{command}"
|
15
|
+
end
|
16
|
+
rescue Mill::Error => e
|
17
|
+
warn e
|
18
|
+
exit(1)
|
19
|
+
end
|
data/lib/mill.rb
CHANGED
@@ -7,330 +7,21 @@ require 'path'
|
|
7
7
|
require 'pp'
|
8
8
|
require 'RedCloth'
|
9
9
|
require 'rubypants'
|
10
|
-
require '
|
10
|
+
require 'sass'
|
11
11
|
require 'time'
|
12
|
-
require 'tidy_ffi'
|
13
|
-
require 'term/ansicolor'
|
14
12
|
|
15
|
-
require 'mill/
|
13
|
+
require 'mill/error'
|
16
14
|
require 'mill/html_helpers'
|
17
15
|
require 'mill/navigator'
|
18
16
|
require 'mill/resource'
|
19
17
|
require 'mill/resources/feed'
|
20
|
-
require 'mill/resources/
|
18
|
+
require 'mill/resources/google_site_verification'
|
21
19
|
require 'mill/resources/image'
|
20
|
+
require 'mill/resources/other'
|
22
21
|
require 'mill/resources/redirect'
|
23
22
|
require 'mill/resources/robots'
|
24
23
|
require 'mill/resources/sitemap'
|
24
|
+
require 'mill/resources/stylesheet'
|
25
25
|
require 'mill/resources/text'
|
26
|
-
require 'mill/
|
27
|
-
|
28
|
-
class Mill
|
29
|
-
|
30
|
-
attr_accessor :input_dir
|
31
|
-
attr_accessor :output_dir
|
32
|
-
attr_accessor :site_title
|
33
|
-
attr_accessor :site_uri
|
34
|
-
attr_accessor :site_email
|
35
|
-
attr_accessor :site_control_date
|
36
|
-
attr_accessor :feed_resource
|
37
|
-
attr_accessor :sitemap_resource
|
38
|
-
attr_accessor :robots_resource
|
39
|
-
attr_accessor :ssh_location
|
40
|
-
attr_accessor :beta_ssh_location
|
41
|
-
attr_accessor :resources
|
42
|
-
attr_accessor :shorten_uris
|
43
|
-
attr_accessor :navigator
|
44
|
-
attr_accessor :navigator_items
|
45
|
-
attr_accessor :resource_classes
|
46
|
-
attr_accessor :schema_types
|
47
|
-
attr_accessor :redirects
|
48
|
-
attr_accessor :input_file_type_order
|
49
|
-
attr_accessor :link_elem_attrs
|
50
|
-
|
51
|
-
DefaultResourceClasses = [
|
52
|
-
Resource::Text,
|
53
|
-
Resource::Image,
|
54
|
-
Resource::Generic,
|
55
|
-
]
|
56
|
-
|
57
|
-
SchemasDir = Path.new(__FILE__).dirname / 'mill' / 'schemas'
|
58
|
-
|
59
|
-
DefaultSchemaTypes = {
|
60
|
-
feed: SchemasDir / 'atom.xsd',
|
61
|
-
sitemap: SchemasDir / 'sitemap.xsd',
|
62
|
-
}
|
63
|
-
|
64
|
-
def initialize(params={})
|
65
|
-
@resource_classes = {}
|
66
|
-
@resources = []
|
67
|
-
@resources_by_uri = {}
|
68
|
-
@schema_types = {}
|
69
|
-
@schemas = {}
|
70
|
-
@shorten_uris = true
|
71
|
-
@input_file_type_order = [:generic, :image, :text]
|
72
|
-
@link_elem_attrs = %w{
|
73
|
-
img/@src
|
74
|
-
script/@src
|
75
|
-
a/@href
|
76
|
-
link/@href
|
77
|
-
stylesheet/@href
|
78
|
-
}
|
79
|
-
params.each { |k, v| send("#{k}=", v) }
|
80
|
-
end
|
81
|
-
|
82
|
-
def input_dir=(path)
|
83
|
-
@input_dir = Path.new(path).expand_path
|
84
|
-
end
|
85
|
-
|
86
|
-
def output_dir=(path)
|
87
|
-
@output_dir = Path.new(path).expand_path
|
88
|
-
end
|
89
|
-
|
90
|
-
def site_uri=(uri)
|
91
|
-
@site_uri = Addressable::URI.parse(uri)
|
92
|
-
end
|
93
|
-
|
94
|
-
def site_control_date=(date)
|
95
|
-
begin
|
96
|
-
@site_control_date = Date.parse(date)
|
97
|
-
rescue ArgumentError => e
|
98
|
-
raise "bad control date #{date.inspect}: #{e}"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def file_type(file)
|
103
|
-
if file.directory? || file.basename.to_s[0] == '.'
|
104
|
-
return :ignore
|
105
|
-
else
|
106
|
-
MIME::Types.of(file.to_s).each do |mime_type|
|
107
|
-
if (type = @file_types[mime_type.content_type])
|
108
|
-
return type
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
nil
|
113
|
-
end
|
114
|
-
|
115
|
-
def add_resource(resource)
|
116
|
-
resource.mill = self
|
117
|
-
begin
|
118
|
-
# ;;warn "loading #{resource.class.type} resource #{resource.uri} as #{resource.class}"
|
119
|
-
resource.load
|
120
|
-
rescue => e
|
121
|
-
warn "Failed to load resource #{resource.uri} (#{resource.class}): #{e}"
|
122
|
-
raise
|
123
|
-
end
|
124
|
-
@resources << resource
|
125
|
-
end
|
126
|
-
|
127
|
-
def update_resource(resource)
|
128
|
-
@resources_by_uri[resource.uri] = resource
|
129
|
-
end
|
130
|
-
|
131
|
-
def find_resource(uri)
|
132
|
-
uri = Addressable::URI.parse(uri.to_s) unless uri.kind_of?(Addressable::URI)
|
133
|
-
resource = @resources_by_uri[uri]
|
134
|
-
if resource.nil? && @shorten_uris
|
135
|
-
uri.path = uri.path.sub(%r{\.html$}, '')
|
136
|
-
resource = @resources_by_uri[uri]
|
137
|
-
end
|
138
|
-
resource
|
139
|
-
end
|
140
|
-
|
141
|
-
def home_resource
|
142
|
-
find_resource('/') or raise "Can't find home"
|
143
|
-
end
|
144
|
-
|
145
|
-
def schema_for_type(type)
|
146
|
-
@schemas[type]
|
147
|
-
end
|
148
|
-
|
149
|
-
def tag_uri
|
150
|
-
"tag:#{@site_uri.host.downcase},#{@site_control_date}:"
|
151
|
-
end
|
152
|
-
|
153
|
-
def feed_generator
|
154
|
-
[
|
155
|
-
'Mill',
|
156
|
-
{
|
157
|
-
uri: Addressable::URI.parse('http://github.com/jslabovitz/mill'),
|
158
|
-
version: Mill::VERSION,
|
159
|
-
}
|
160
|
-
]
|
161
|
-
end
|
162
|
-
|
163
|
-
def feed_author_name
|
164
|
-
@site_title
|
165
|
-
end
|
166
|
-
|
167
|
-
def feed_author_uri
|
168
|
-
@site_uri
|
169
|
-
end
|
170
|
-
|
171
|
-
def feed_author_email
|
172
|
-
@site_email
|
173
|
-
end
|
174
|
-
|
175
|
-
def public_resources
|
176
|
-
@resources.select(&:public)
|
177
|
-
end
|
178
|
-
|
179
|
-
def clean
|
180
|
-
@output_dir.rmtree if @output_dir.exist?
|
181
|
-
@output_dir.mkpath
|
182
|
-
end
|
183
|
-
|
184
|
-
def load
|
185
|
-
warn "loading resources..."
|
186
|
-
build_file_types
|
187
|
-
build_resource_classes
|
188
|
-
build_schemas
|
189
|
-
load_files
|
190
|
-
load_others
|
191
|
-
end
|
192
|
-
|
193
|
-
def load_others
|
194
|
-
make_redirects
|
195
|
-
make_feed
|
196
|
-
make_sitemap
|
197
|
-
make_robots
|
198
|
-
make_navigator
|
199
|
-
end
|
200
|
-
|
201
|
-
def build
|
202
|
-
warn "building #{@resources.length} resources..."
|
203
|
-
@resources.each do |resource|
|
204
|
-
begin
|
205
|
-
resource.build
|
206
|
-
rescue => e
|
207
|
-
warn "Failed to build resource #{resource.uri}: #{e}"
|
208
|
-
raise
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def publish(mode=:final)
|
214
|
-
location = case mode
|
215
|
-
when :final
|
216
|
-
@ssh_location
|
217
|
-
when :beta
|
218
|
-
@beta_ssh_location
|
219
|
-
else
|
220
|
-
raise "Unknown publish mode: #{mode.inspect}"
|
221
|
-
end
|
222
|
-
raise "Must specify SSH location" unless location
|
223
|
-
system('rsync',
|
224
|
-
# '--dry-run',
|
225
|
-
'--archive',
|
226
|
-
'--delete-after',
|
227
|
-
'--progress',
|
228
|
-
# '--verbose',
|
229
|
-
@output_dir.to_s + '/',
|
230
|
-
location,
|
231
|
-
)
|
232
|
-
end
|
233
|
-
|
234
|
-
def server
|
235
|
-
SimpleServer.run!(
|
236
|
-
root: @output_dir,
|
237
|
-
multihosting: false,
|
238
|
-
)
|
239
|
-
end
|
240
|
-
|
241
|
-
private
|
242
|
-
|
243
|
-
def load_files
|
244
|
-
input_files_by_type.each do |type, input_files|
|
245
|
-
input_files.each do |input_file|
|
246
|
-
resource_class = @resource_classes[type] or raise "No resource class for #{input_file}"
|
247
|
-
resource = resource_class.new(
|
248
|
-
input_file: input_file,
|
249
|
-
output_file: @output_dir / input_file.relative_to(@input_dir))
|
250
|
-
add_resource(resource)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def input_files_by_type
|
256
|
-
hash = {}
|
257
|
-
raise "Input path not found: #{@input_dir}" unless @input_dir.exist?
|
258
|
-
@input_dir.find do |input_file|
|
259
|
-
input_file = @input_dir / input_file
|
260
|
-
type = file_type(input_file) or raise "Can't determine file type of #{input_file}"
|
261
|
-
unless type == :ignore
|
262
|
-
hash[type] ||= []
|
263
|
-
hash[type] << input_file
|
264
|
-
end
|
265
|
-
end
|
266
|
-
hash.sort_by { |t, f| input_file_type_order.index(t) || input_file_type_order.length }
|
267
|
-
end
|
268
|
-
|
269
|
-
def make_feed
|
270
|
-
@feed_resource = Resource::Feed.new(
|
271
|
-
output_file: @output_dir / 'feed.xml')
|
272
|
-
add_resource(@feed_resource)
|
273
|
-
end
|
274
|
-
|
275
|
-
def make_sitemap
|
276
|
-
@sitemap_resource = Resource::Sitemap.new(
|
277
|
-
output_file: @output_dir / 'sitemap.xml')
|
278
|
-
add_resource(@sitemap_resource)
|
279
|
-
end
|
280
|
-
|
281
|
-
def make_robots
|
282
|
-
@robots_resource = Resource::Robots.new(
|
283
|
-
output_file: @output_dir / 'robots.txt')
|
284
|
-
add_resource(@robots_resource)
|
285
|
-
end
|
286
|
-
|
287
|
-
def make_navigator
|
288
|
-
if @navigator_items
|
289
|
-
@navigator = Navigator.new
|
290
|
-
@navigator.items = @navigator_items.map do |uri, title|
|
291
|
-
uri = Addressable::URI.parse(uri)
|
292
|
-
if title.nil? && uri.relative?
|
293
|
-
resource = find_resource(uri) or raise "Can't find navigation resource for URI #{uri}"
|
294
|
-
title = resource.title
|
295
|
-
end
|
296
|
-
Navigator::Item.new(uri: uri, title: title)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
def make_redirects
|
302
|
-
return unless @redirects
|
303
|
-
@redirects.each do |from, to|
|
304
|
-
output_file = @output_dir / Path.new(from).relative_to('/')
|
305
|
-
resource = Resource::Redirect.new(
|
306
|
-
output_file: output_file,
|
307
|
-
redirect_uri: to)
|
308
|
-
add_resource(resource)
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
def build_schemas
|
313
|
-
DefaultSchemaTypes.merge(@schema_types).each do |type, file|
|
314
|
-
;;warn "loading schema #{type} from #{file}"
|
315
|
-
@schemas[type] = Nokogiri::XML::Schema(file.open) { |c| c.strict.nonet }
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
def build_file_types
|
320
|
-
@file_types = {}
|
321
|
-
FileTypes.each do |type, mime_types|
|
322
|
-
mime_types.each do |mime_type|
|
323
|
-
MIME::Types[mime_type].each do |t|
|
324
|
-
@file_types[t.content_type] = type
|
325
|
-
end
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
def build_resource_classes
|
331
|
-
@resource_classes = Hash[
|
332
|
-
(DefaultResourceClasses + @resource_classes).map { |rc| [rc.type, rc] }
|
333
|
-
]
|
334
|
-
end
|
335
|
-
|
336
|
-
end
|
26
|
+
require 'mill/site'
|
27
|
+
require 'mill/version'
|