mill 0.16 → 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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/Rakefile +1 -9
- data/TODO.md +4 -0
- data/bin/mill +1 -27
- data/lib/mill/command.rb +13 -0
- data/lib/mill/commands/build.rb +17 -0
- data/lib/mill/commands/check.rb +16 -0
- data/lib/mill/commands/diff.rb +18 -0
- data/lib/mill/commands/list.rb +20 -0
- data/lib/mill/commands/snapshot.rb +20 -0
- data/lib/mill/commands/tree.rb +17 -0
- data/lib/mill/commands/types.rb +18 -0
- data/lib/mill/commands/upload.rb +24 -0
- data/lib/mill/config.rb +27 -0
- data/lib/mill/resource.rb +74 -87
- data/lib/mill/resources/blob.rb +4 -0
- data/lib/mill/resources/feed.rb +5 -13
- data/lib/mill/resources/image.rb +10 -18
- data/lib/mill/resources/markdown.rb +20 -0
- data/lib/mill/resources/markup.rb +62 -0
- data/lib/mill/resources/page.rb +140 -0
- data/lib/mill/resources/redirect.rb +17 -16
- data/lib/mill/resources/robots.rb +3 -4
- data/lib/mill/resources/sitemap.rb +3 -5
- data/lib/mill/resources/stylesheet.rb +4 -4
- data/lib/mill/resources/textile.rb +27 -0
- data/lib/mill/resources.rb +89 -0
- data/lib/mill/site.rb +182 -283
- data/lib/mill.rb +27 -9
- data/mill.gemspec +19 -19
- data/test/content/c.md +4 -0
- data/test/content/d.md +4 -0
- data/test/main_test.rb +68 -0
- data/test/mill.yaml +8 -0
- metadata +118 -51
- data/Gemfile +0 -6
- data/TODO.txt +0 -61
- data/lib/mill/html_helpers.rb +0 -128
- data/lib/mill/navigator.rb +0 -61
- data/lib/mill/resources/dir.rb +0 -31
- data/lib/mill/resources/google_site_verification.rb +0 -30
- data/lib/mill/resources/text.rb +0 -218
- data/lib/mill/version.rb +0 -5
- data/test/test.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72216a7795be9cfd8a2039e3eac35f73f4c129a30e951074c638d6c77088c869
|
4
|
+
data.tar.gz: aead637972f953d1d01aaee384554766361cfb4d9efa1ae95a6aaa2e2e5e6d11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34d154f5a9cfa6e0a10d4abc57c7d3d99e18e857b1457e5ab9fbf82b50d426f469ed8cd79dc8821cdcddcf9e7fc95920d868b2025a0a328fdab9624e7d83d115
|
7
|
+
data.tar.gz: 8c433c5295ad53229ac23473eddd21b12995f225beb542e9c4d64ecafbec63d215fa343630e3380b5b162b62fd63c29eeba9b58f0404cf281aa89c36ef666bd2
|
data/LICENSE
CHANGED
data/Rakefile
CHANGED
data/TODO.md
ADDED
data/bin/mill
CHANGED
@@ -2,30 +2,4 @@
|
|
2
2
|
|
3
3
|
require 'mill'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
begin
|
8
|
-
case (command = ARGV.shift)
|
9
|
-
when nil, 'make'
|
10
|
-
$site.make
|
11
|
-
when 'clean'
|
12
|
-
$site.clean
|
13
|
-
when 'check'
|
14
|
-
$site.check
|
15
|
-
when 'list'
|
16
|
-
$site.list
|
17
|
-
when 'diff'
|
18
|
-
$site.diff
|
19
|
-
when 'snapshot'
|
20
|
-
$site.snapshot
|
21
|
-
when 'upload'
|
22
|
-
$site.upload
|
23
|
-
when 'show'
|
24
|
-
puts $site.send(ARGV.shift)
|
25
|
-
else
|
26
|
-
raise "Unknown command: #{command.inspect}"
|
27
|
-
end
|
28
|
-
rescue Mill::Error => e
|
29
|
-
warn e
|
30
|
-
exit(1)
|
31
|
-
end
|
5
|
+
Simple::CommandParser.run(ARGV)
|
data/lib/mill/command.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mill
|
2
|
+
|
3
|
+
module Commands
|
4
|
+
|
5
|
+
class Snapshot < Command
|
6
|
+
|
7
|
+
def run(args)
|
8
|
+
super
|
9
|
+
@site.output_dir.chdir do
|
10
|
+
run_command(%w[git init]) unless Path.new('.git').exist?
|
11
|
+
run_command(%w[git add .])
|
12
|
+
run_command(%w[git commit -a -m Update.])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Mill
|
2
|
+
|
3
|
+
module Commands
|
4
|
+
|
5
|
+
class Upload < Command
|
6
|
+
|
7
|
+
def run(args)
|
8
|
+
super
|
9
|
+
raise "site_rsync not defined" unless @site.site_rsync
|
10
|
+
options = %w[
|
11
|
+
--progress
|
12
|
+
--verbose
|
13
|
+
--archive
|
14
|
+
--exclude=.git
|
15
|
+
--delete-after
|
16
|
+
]
|
17
|
+
run_command('rsync', *options, @site.output_dir, @site.site_rsync, verbose: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/mill/config.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mill
|
2
|
+
|
3
|
+
ConfigFileName = 'mill.yaml'
|
4
|
+
|
5
|
+
BaseConfig = Simple::Configurator.define(
|
6
|
+
dir: { default: '.', converter: :path },
|
7
|
+
input_dir: { default: 'content', converter: :path },
|
8
|
+
output_dir: { default: 'public_html', converter: :path },
|
9
|
+
code_dir: { default: 'code', converter: :path },
|
10
|
+
site_uri: { default: 'http://localhost', converter: :uri },
|
11
|
+
site_rsync: nil,
|
12
|
+
site_title: nil,
|
13
|
+
site_email: nil,
|
14
|
+
site_twitter: { converter: :uri },
|
15
|
+
site_instagram: { converter: :uri },
|
16
|
+
site_postal: nil,
|
17
|
+
site_phone: nil,
|
18
|
+
site_control_date: { converter: :date },
|
19
|
+
html_version: { default: :html5, converter: :symbol },
|
20
|
+
make_error: true,
|
21
|
+
make_feed: true,
|
22
|
+
make_sitemap: true,
|
23
|
+
make_robots: true,
|
24
|
+
allow_robots: true,
|
25
|
+
)
|
26
|
+
|
27
|
+
end
|
data/lib/mill/resource.rb
CHANGED
@@ -4,123 +4,105 @@ module Mill
|
|
4
4
|
|
5
5
|
FileTypes = []
|
6
6
|
|
7
|
-
attr_accessor :input_file
|
8
|
-
attr_accessor :output_file
|
9
7
|
attr_accessor :path
|
8
|
+
attr_accessor :uri
|
9
|
+
attr_accessor :primary
|
10
|
+
attr_accessor :input
|
10
11
|
attr_accessor :date
|
11
|
-
|
12
|
-
attr_accessor :content
|
12
|
+
attr_reader :output
|
13
13
|
attr_accessor :site
|
14
14
|
attr_accessor :node
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@input_file = Path.new(input_file)
|
24
|
-
@date = input_file.mtime.to_datetime
|
25
|
-
else
|
26
|
-
@date = DateTime.now
|
27
|
-
end
|
28
|
-
if output_file
|
29
|
-
@output_file = Path.new(output_file)
|
30
|
-
@path = '/' + @output_file.relative_to(site.output_dir).to_s
|
31
|
-
end
|
32
|
-
self.date = date if date
|
33
|
-
self.public = public
|
34
|
-
@content = content
|
35
|
-
@site = site
|
36
|
-
end
|
37
|
-
|
38
|
-
def date=(date)
|
39
|
-
@date = case date
|
40
|
-
when String, Time
|
41
|
-
begin
|
42
|
-
DateTime.parse(date.to_s)
|
43
|
-
rescue ArgumentError => e
|
44
|
-
raise Error, "Can't parse date: #{date.inspect}"
|
45
|
-
end
|
46
|
-
when Date, DateTime, nil
|
47
|
-
date
|
48
|
-
else
|
49
|
-
raise Error, "Can't assign 'date' attribute: #{date.inspect}"
|
16
|
+
include SetParams
|
17
|
+
include Simple::Printer::Printable
|
18
|
+
|
19
|
+
def initialize(params={})
|
20
|
+
super({ primary: false }.merge(params))
|
21
|
+
unless defined?(@date)
|
22
|
+
@date = @input&.kind_of?(Path) ? @input.mtime.to_datetime : DateTime.now
|
50
23
|
end
|
24
|
+
@uri = Addressable::URI.encode(@path, Addressable::URI)
|
51
25
|
end
|
52
26
|
|
53
|
-
def
|
54
|
-
|
55
|
-
when 'false', FalseClass
|
56
|
-
false
|
57
|
-
when 'true', TrueClass
|
58
|
-
true
|
59
|
-
else
|
60
|
-
raise Error, "Can't assign 'public' attribute: #{public.inspect}"
|
61
|
-
end
|
27
|
+
def inspect
|
28
|
+
"<#{self.class}>"
|
62
29
|
end
|
63
30
|
|
64
|
-
def
|
65
|
-
@
|
31
|
+
def primary?
|
32
|
+
@primary
|
66
33
|
end
|
67
34
|
|
68
|
-
def
|
69
|
-
|
35
|
+
def root?
|
36
|
+
self == @site.root_resource
|
70
37
|
end
|
71
38
|
|
72
|
-
def
|
73
|
-
|
39
|
+
def output_file
|
40
|
+
if @site && @path
|
41
|
+
@site.output_dir / Path.new(@path).relative_to('/')
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
74
45
|
end
|
75
46
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
children.map(&:path),
|
47
|
+
def printable
|
48
|
+
[
|
49
|
+
:path,
|
50
|
+
{ key: :input, value: input_description },
|
51
|
+
{ key: :output_file, value: (o = output_file) ? o.relative_to(@site.output_dir).to_s : nil },
|
52
|
+
:date,
|
53
|
+
:primary?,
|
54
|
+
:class,
|
55
|
+
{ label: 'Parent', value: parent&.path || '-' },
|
56
|
+
{ label: 'Siblings', value: siblings&.map(&:path)&.join(', ') || '-' },
|
57
|
+
{ label: 'Children', value: children&.map(&:path)&.join(', ') || '-' },
|
88
58
|
]
|
89
59
|
end
|
90
60
|
|
61
|
+
def input_description
|
62
|
+
case @input
|
63
|
+
when Path
|
64
|
+
@input.relative_to(@site.input_dir).to_s
|
65
|
+
when String
|
66
|
+
(@input[0...100] + '...').inspect
|
67
|
+
when nil
|
68
|
+
'-'
|
69
|
+
else
|
70
|
+
"<#{@input.class}>"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
91
74
|
def parent
|
92
|
-
@node
|
75
|
+
@node&.parent&.content
|
93
76
|
end
|
94
77
|
|
95
78
|
def siblings
|
96
|
-
@node.siblings.map(&:content).compact
|
79
|
+
@node ? @node.siblings.map(&:content).compact : []
|
97
80
|
end
|
98
81
|
|
99
|
-
def
|
100
|
-
@node
|
82
|
+
def previous_sibling
|
83
|
+
@node&.previous_sibling&.content
|
101
84
|
end
|
102
85
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
86
|
+
def next_sibling
|
87
|
+
@node&.next_sibling&.content
|
88
|
+
end
|
89
|
+
|
90
|
+
def children
|
91
|
+
@node ? @node.children.map(&:content).compact : []
|
106
92
|
end
|
107
93
|
|
108
94
|
def absolute_uri
|
109
|
-
@site.site_uri + uri
|
95
|
+
@site.site_uri + @uri
|
110
96
|
end
|
111
97
|
|
112
98
|
def tag_uri
|
113
|
-
@site.tag_uri + uri
|
99
|
+
@site.tag_uri + @uri
|
114
100
|
end
|
115
101
|
|
116
102
|
def change_frequency
|
117
103
|
:weekly
|
118
104
|
end
|
119
105
|
|
120
|
-
def final_content
|
121
|
-
@content
|
122
|
-
end
|
123
|
-
|
124
106
|
def load
|
125
107
|
# implemented in subclass
|
126
108
|
end
|
@@ -130,16 +112,21 @@ module Mill
|
|
130
112
|
end
|
131
113
|
|
132
114
|
def save
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
@
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
@
|
115
|
+
file = output_file
|
116
|
+
file.dirname.mkpath
|
117
|
+
if @output
|
118
|
+
# ;;warn "#{@path}: writing output to #{file}"
|
119
|
+
file.write(@output)
|
120
|
+
file.utime(@date.to_time, @date.to_time)
|
121
|
+
elsif @input.kind_of?(Path)
|
122
|
+
# ;;warn "#{@path}: copying #{@input} to #{file}"
|
123
|
+
@input.copy(file)
|
124
|
+
elsif @input
|
125
|
+
# ;;warn "#{@path}: writing input to #{file}"
|
126
|
+
file.write(@input)
|
127
|
+
file.utime(@date.to_time, @date.to_time)
|
141
128
|
else
|
142
|
-
raise Error, "Can't build resource without
|
129
|
+
raise Error, "#{@path}: Can't build resource without output or input file"
|
143
130
|
end
|
144
131
|
end
|
145
132
|
|
data/lib/mill/resources/blob.rb
CHANGED
@@ -5,6 +5,8 @@ module Mill
|
|
5
5
|
class Blob < Resource
|
6
6
|
|
7
7
|
FileTypes = %w{
|
8
|
+
text/plain
|
9
|
+
|
8
10
|
application/pdf
|
9
11
|
|
10
12
|
application/zip
|
@@ -16,9 +18,11 @@ module Mill
|
|
16
18
|
application/x-javascript
|
17
19
|
|
18
20
|
font/otf
|
21
|
+
font/woff2
|
19
22
|
application/font-sfnt
|
20
23
|
application/x-font-opentype
|
21
24
|
application/x-font-otf
|
25
|
+
application/font-woff
|
22
26
|
|
23
27
|
application/mp4
|
24
28
|
audio/mpeg
|
data/lib/mill/resources/feed.rb
CHANGED
@@ -1,20 +1,16 @@
|
|
1
|
-
# see http://www.sitemaps.org/protocol.php
|
2
|
-
|
3
1
|
module Mill
|
4
2
|
|
5
3
|
class Resource
|
6
4
|
|
7
5
|
class Feed < Resource
|
8
6
|
|
9
|
-
include HTMLHelpers
|
10
|
-
|
11
7
|
def build
|
12
8
|
resources = @site.feed_resources
|
13
|
-
|
9
|
+
@output = Nokogiri::XML::Builder.new do |xml|
|
14
10
|
xml.feed(xmlns: 'http://www.w3.org/2005/Atom') do
|
15
11
|
xml.id(@site.tag_uri)
|
16
12
|
xml.title(@site.site_title) if @site.site_title
|
17
|
-
xml.link(rel: 'alternate', type: 'text/html', href: @site.
|
13
|
+
xml.link(rel: 'alternate', type: 'text/html', href: @site.root_resource.absolute_uri) if @site.root_resource
|
18
14
|
xml.link(rel: 'self', type: 'application/atom+xml', href: absolute_uri)
|
19
15
|
xml.author do
|
20
16
|
xml.name(@site.feed_author_name) if @site.feed_author_name
|
@@ -35,15 +31,11 @@ module Mill
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
38
|
-
end
|
39
|
-
@content = builder.doc
|
40
|
-
super
|
34
|
+
end.doc
|
41
35
|
end
|
42
36
|
|
43
|
-
def
|
44
|
-
|
45
|
-
html.link(href: uri, rel: 'alternate', type: 'application/atom+xml')
|
46
|
-
end
|
37
|
+
def build_link(html)
|
38
|
+
html.link(href: uri, rel: 'alternate', type: 'application/atom+xml')
|
47
39
|
end
|
48
40
|
|
49
41
|
end
|
data/lib/mill/resources/image.rb
CHANGED
@@ -4,8 +4,6 @@ module Mill
|
|
4
4
|
|
5
5
|
class Image < Resource
|
6
6
|
|
7
|
-
include HTMLHelpers
|
8
|
-
|
9
7
|
FileTypes = %w{
|
10
8
|
image/gif
|
11
9
|
image/jpeg
|
@@ -18,27 +16,21 @@ module Mill
|
|
18
16
|
attr_accessor :width
|
19
17
|
attr_accessor :height
|
20
18
|
|
21
|
-
def
|
22
|
-
super +
|
23
|
-
|
24
|
-
|
19
|
+
def printable
|
20
|
+
super + [
|
21
|
+
:width,
|
22
|
+
:height,
|
25
23
|
]
|
26
24
|
end
|
27
25
|
|
28
26
|
def load
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def img_html
|
35
|
-
html_fragment do |html|
|
36
|
-
html.img(
|
37
|
-
src: uri,
|
38
|
-
alt: @title,
|
39
|
-
height: @height,
|
40
|
-
width: @width)
|
27
|
+
raise Error, "Input must be file" unless @input.kind_of?(Path)
|
28
|
+
begin
|
29
|
+
info = ImageSize.path(@input.to_s)
|
30
|
+
rescue => e
|
31
|
+
raise Error, "Can't load image file #{@input.to_s.inspect}: #{e}"
|
41
32
|
end
|
33
|
+
@width, @height = *info.size
|
42
34
|
end
|
43
35
|
|
44
36
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Mill
|
2
|
+
|
3
|
+
class Resource
|
4
|
+
|
5
|
+
class Markup < Resource
|
6
|
+
|
7
|
+
def printable
|
8
|
+
super + [
|
9
|
+
:header,
|
10
|
+
{ label: 'Text', value: @text[0...100] + '...' },
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
def load
|
15
|
+
@text = case @input
|
16
|
+
when Path
|
17
|
+
@input.read
|
18
|
+
when String
|
19
|
+
@input.dup
|
20
|
+
else
|
21
|
+
raise Error, "Unknown markup input: #{@input.class}"
|
22
|
+
end
|
23
|
+
@header = HashStruct.new
|
24
|
+
if @text.split(/\n/, 2).first =~ /^\w+:\s+/
|
25
|
+
fields = {}
|
26
|
+
lines, @text = @text.split(/\n\n/, 2)
|
27
|
+
lines.split(/\n/).each do |line|
|
28
|
+
if line.start_with?(/\s+/)
|
29
|
+
key = fields.keys.last
|
30
|
+
fields[key] += line
|
31
|
+
else
|
32
|
+
key, value = line.strip.split(/:\s*/, 2)
|
33
|
+
fields[key] = value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@header = HashStruct.new(fields)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_text(text)
|
41
|
+
# implemented in subclass
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_class
|
45
|
+
@site.resource_class_for_type('text/html')
|
46
|
+
end
|
47
|
+
|
48
|
+
def convert
|
49
|
+
return nil if @header[:draft]
|
50
|
+
convert_class.new(
|
51
|
+
path: @path.sub(%r{\.\w+$}, '.html'),
|
52
|
+
input: parse_text(@text),
|
53
|
+
date: @date,
|
54
|
+
**@header,
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|