middleman-webcomic 0.5.0
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.
- data/.gitignore +5 -0
- data/ChangeLog.md +11 -0
- data/Gemfile +3 -0
- data/License +18 -0
- data/Rakefile +22 -0
- data/Readme.md +22 -0
- data/lib/middleman-webcomic/cli.rb +5 -0
- data/lib/middleman-webcomic/data.rb +213 -0
- data/lib/middleman-webcomic/feature.rb +172 -0
- data/lib/middleman-webcomic/mock_app.rb +31 -0
- data/lib/middleman-webcomic/pager.rb +51 -0
- data/lib/middleman-webcomic/tasks.rb +53 -0
- data/lib/middleman-webcomic/template/Gemfile.tt +7 -0
- data/lib/middleman-webcomic/template/Rakefile.tt +28 -0
- data/lib/middleman-webcomic/template/config.ru +16 -0
- data/lib/middleman-webcomic/template/config.tt +71 -0
- data/lib/middleman-webcomic/template/source/about.html.slim +11 -0
- data/lib/middleman-webcomic/template/source/comics/index.html.slim +14 -0
- data/lib/middleman-webcomic/template/source/comics/template.html.slim +1 -0
- data/lib/middleman-webcomic/template/source/feed.xml.builder +30 -0
- data/lib/middleman-webcomic/template/source/index.html.slim +1 -0
- data/lib/middleman-webcomic/template/source/layout.slim +63 -0
- data/lib/middleman-webcomic/template/source/robots.txt +3 -0
- data/lib/middleman-webcomic/template/source/theme/_comic.slim +4 -0
- data/lib/middleman-webcomic/template/source/theme/_layout_tall.slim +17 -0
- data/lib/middleman-webcomic/template/source/theme/_layout_wide.slim +16 -0
- data/lib/middleman-webcomic/template/source/theme/_sidebar.slim +13 -0
- data/lib/middleman-webcomic/template/source/theme/images/favicon.png +0 -0
- data/lib/middleman-webcomic/template/source/theme/scripts/app.js.coffee +4 -0
- data/lib/middleman-webcomic/template/source/theme/styles/_utils.scss +399 -0
- data/lib/middleman-webcomic/template/source/theme/styles/screen.css.sass +89 -0
- data/lib/middleman-webcomic/template.rb +30 -0
- data/lib/middleman-webcomic/version.rb +7 -0
- data/lib/middleman-webcomic.rb +11 -0
- data/lib/middleman_init.rb +1 -0
- data/middleman-webcomic.gemspec +29 -0
- metadata +113 -0
data/.gitignore
ADDED
data/ChangeLog.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# v0.5.0
|
|
2
|
+
- Updated to support Middleman's new auto-discovery.
|
|
3
|
+
- Includes boilerplate site.
|
|
4
|
+
|
|
5
|
+
# v0.4.0
|
|
6
|
+
- Added storyline support and helpers.
|
|
7
|
+
|
|
8
|
+
This introduces a breaking change to how the data is added to middle data_content, fortunately I'm the only one using it right now. :)
|
|
9
|
+
|
|
10
|
+
# v0.2.1
|
|
11
|
+
- Initial release. Yay!
|
data/Gemfile
ADDED
data/License
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Copyright (C) 2011 by Matt McCray
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
data/Rakefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
|
2
|
+
require "middleman-webcomic/version"
|
|
3
|
+
|
|
4
|
+
desc "builds gem"
|
|
5
|
+
task :build do
|
|
6
|
+
system "gem build middleman-webcomic.gemspec"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
desc "releases gem"
|
|
10
|
+
task :release => :build do
|
|
11
|
+
system "gem push middleman-webcomic-#{Middleman::Webcomic::VERSION}.gem"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc "installs gem"
|
|
15
|
+
task :install => :build do
|
|
16
|
+
system "gem install middleman-webcomic-#{Middleman::Webcomic::VERSION}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc "uninstalls gem"
|
|
20
|
+
task :uninstall do
|
|
21
|
+
system "gem uninstall middleman-webcomic"
|
|
22
|
+
end
|
data/Readme.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Webcomic for MiddleMan
|
|
2
|
+
|
|
3
|
+
*Updated for Middleman auto-discovery.*
|
|
4
|
+
|
|
5
|
+
After you install the gem:
|
|
6
|
+
|
|
7
|
+
gem install middleman-webcomic
|
|
8
|
+
|
|
9
|
+
Create a new webcomic site like this:
|
|
10
|
+
|
|
11
|
+
middleman init MY_SITE --template=webcomic
|
|
12
|
+
|
|
13
|
+
Then customize to your satisfaction.
|
|
14
|
+
|
|
15
|
+
# Live Sites
|
|
16
|
+
|
|
17
|
+
This extension is used in conjunction with MiddleMan on the following sites:
|
|
18
|
+
|
|
19
|
+
* [ZooDotCom](http://www.zoodotcom.com)
|
|
20
|
+
* [Tactless Comics](http://tactless.inkwellian.com)
|
|
21
|
+
* [Darkshore Detectives](http://darkshore.inkwellian.com)
|
|
22
|
+
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
require 'date'
|
|
3
|
+
|
|
4
|
+
class String
|
|
5
|
+
def create_slug
|
|
6
|
+
s= self.downcase.gsub(/'/, '').gsub(/[^a-z0-9]+/, '-')
|
|
7
|
+
s.chop! if s[-1] == '-'
|
|
8
|
+
s
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Middleman
|
|
13
|
+
|
|
14
|
+
module Webcomic
|
|
15
|
+
|
|
16
|
+
def self.load_from(path, app)
|
|
17
|
+
all= []
|
|
18
|
+
Dir["#{path}/*.comic*"].each do |filename| # Hardcoded for markdown... For now
|
|
19
|
+
comic = Comic.new(filename, app)
|
|
20
|
+
#puts comic.pub_date.inspect
|
|
21
|
+
all << comic if comic.publishable?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if app.settings.webcomic_sort_by == :publish_date
|
|
25
|
+
all.sort! {|x,y| y.pub_date <=> x.pub_date }
|
|
26
|
+
else
|
|
27
|
+
fld= app.settings.webcomic_sort_by
|
|
28
|
+
all.sort! {|x,y| y[fld] <=> x[fld] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Update all the position info...
|
|
32
|
+
cl= all.length
|
|
33
|
+
all.each_with_index do |comic, i|
|
|
34
|
+
comic[:position]= (cl - i)
|
|
35
|
+
comic[:index]= i
|
|
36
|
+
comic.first= all[-1]
|
|
37
|
+
comic.last= all[0]
|
|
38
|
+
comic.next= i > 0 ? all[i - 1] : nil
|
|
39
|
+
comic.prev= i < (cl - 1) ? all[i + 1] : nil
|
|
40
|
+
if app.settings.webcomic_enable_stories and comic.story
|
|
41
|
+
Story.find_or_create_for comic
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
stories= Story.all
|
|
46
|
+
stories.sort! {|x,y| y.pub_date <=> x.pub_date }
|
|
47
|
+
sl= stories.length
|
|
48
|
+
stories.each_with_index do |story, i|
|
|
49
|
+
story.position= (sl - i)
|
|
50
|
+
# puts "##{story.position} - #{story.title}(#{story.slug}): #{story.comics.length}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
[all, stories]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Story
|
|
57
|
+
attr_accessor :title, :slug, :comics, :position
|
|
58
|
+
|
|
59
|
+
def initialize(title)
|
|
60
|
+
@title= title
|
|
61
|
+
@slug= @title.create_slug
|
|
62
|
+
@comics= []
|
|
63
|
+
@position= nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def pub_date
|
|
67
|
+
@comics.last.pub_date
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def add_comic(comic)
|
|
71
|
+
@comics << comic
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class << self
|
|
75
|
+
|
|
76
|
+
def all
|
|
77
|
+
@stories ||= {}
|
|
78
|
+
@stories.values
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def find_or_create_for(comic)
|
|
82
|
+
title= comic.story
|
|
83
|
+
@stories ||= {}
|
|
84
|
+
unless @stories.has_key? title
|
|
85
|
+
story= @stories[title]= new(title)
|
|
86
|
+
end
|
|
87
|
+
@stories[title].add_comic comic
|
|
88
|
+
@stories[title]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class Comic
|
|
94
|
+
|
|
95
|
+
attr_accessor :content, :source, :metadata, :path, :next, :prev, :first, :last
|
|
96
|
+
|
|
97
|
+
def initialize(path, app)
|
|
98
|
+
@app= app
|
|
99
|
+
settings= app.settings
|
|
100
|
+
@path= path
|
|
101
|
+
@source= ""
|
|
102
|
+
@content= ""
|
|
103
|
+
@next= nil
|
|
104
|
+
@prev= nil
|
|
105
|
+
@first= nil
|
|
106
|
+
@last= nil
|
|
107
|
+
@metadata= ::Thor::CoreExt::HashWithIndifferentAccess.new({})
|
|
108
|
+
@metadata[:ext]= File.extname(path)
|
|
109
|
+
@metadata[:publish_date]= Date.today #Time.now.strftime "%Y-%m-%d"
|
|
110
|
+
@metadata[:slug]= File.basename(path).gsub( @metadata[:ext], '').gsub('.comic','')
|
|
111
|
+
|
|
112
|
+
if /^([\d]{2})([\d]{2})([\d]{2})\-(.*)(\.comic#{@metadata[:ext]})$/ =~ File.basename(path)
|
|
113
|
+
year= "20#{ $1 }"
|
|
114
|
+
month= $2
|
|
115
|
+
day= $3
|
|
116
|
+
@metadata[:publish_date]= Date.parse "#{year}-#{month}-#{day}"
|
|
117
|
+
@metadata[:slug]= $4
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
@metadata[:title]= @metadata[:slug].titleize rescue @metadata[:slug]
|
|
121
|
+
@metadata[:slug]= @metadata[:slug].downcase
|
|
122
|
+
|
|
123
|
+
# Parse yaml header...
|
|
124
|
+
begin
|
|
125
|
+
read_yaml()
|
|
126
|
+
rescue
|
|
127
|
+
puts "Error reading YAML! #{self.slug}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
if self.filename.nil?
|
|
131
|
+
throw "Filename Missing: Comics must define a filename! (#{self.slug})"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if publishable?
|
|
135
|
+
# Dont' waste time if it's not a publishable comic
|
|
136
|
+
engine= Tilt[path].new { @source }
|
|
137
|
+
@content= engine.render
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def [](key)
|
|
142
|
+
@metadata[key]
|
|
143
|
+
end
|
|
144
|
+
def []=(key, value)
|
|
145
|
+
#puts "Setting #{key} to #{value}"
|
|
146
|
+
@metadata[key]= value
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def method_missing(key, value=nil)
|
|
150
|
+
if @metadata.has_key? key
|
|
151
|
+
@metadata[key]
|
|
152
|
+
elsif @metadata.has_key? key.to_s
|
|
153
|
+
@metadata[key.to_s]
|
|
154
|
+
else
|
|
155
|
+
#super Should it throw an error?
|
|
156
|
+
nil
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def to_json *a
|
|
161
|
+
data= @metadata.reject {|k,v| k == :ext or k == "ext" }
|
|
162
|
+
data.to_json *a
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def publishable?
|
|
166
|
+
@is_publishable ||= begin
|
|
167
|
+
now= Time.now
|
|
168
|
+
now_string = now.strftime "%Y-%m-%d"
|
|
169
|
+
today= Date.parse(now_string)
|
|
170
|
+
pubdate= self.pub_date
|
|
171
|
+
case pubdate
|
|
172
|
+
when String
|
|
173
|
+
self['publish_date']= Date.parse(pubdate)
|
|
174
|
+
pubdate <= now_string
|
|
175
|
+
when Time
|
|
176
|
+
self['publish_date']= Date.parse(pubdate.strftime('%Y-%m-%d'))
|
|
177
|
+
pubdate <= now
|
|
178
|
+
when Date
|
|
179
|
+
pubdate <= today
|
|
180
|
+
else
|
|
181
|
+
true
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def pub_date
|
|
187
|
+
date= self.publish_on || self.publish_date || self.date
|
|
188
|
+
case date
|
|
189
|
+
when String
|
|
190
|
+
Date.parse(date)
|
|
191
|
+
when Time
|
|
192
|
+
Date.parse(date.strftime('%Y-%m-%d'))
|
|
193
|
+
when Date
|
|
194
|
+
date
|
|
195
|
+
else
|
|
196
|
+
Date.today
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
private
|
|
201
|
+
|
|
202
|
+
def read_yaml()
|
|
203
|
+
@raw = File.read(@path)
|
|
204
|
+
data, source= @app.parse_front_matter @raw
|
|
205
|
+
data.each_pair do |k,v|
|
|
206
|
+
@metadata[k]= v
|
|
207
|
+
end
|
|
208
|
+
@source= source
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module Middleman
|
|
4
|
+
module Features
|
|
5
|
+
module Webcomic
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
def registered(app)
|
|
9
|
+
puts "Webcomic v#{::Middleman::Webcomic::VERSION}"
|
|
10
|
+
|
|
11
|
+
# Default settings:
|
|
12
|
+
app.set :webcomic_images, "images/comics"
|
|
13
|
+
app.set :webcomic_source, "comics"
|
|
14
|
+
app.set :webcomic_source_images, "comics/images"
|
|
15
|
+
app.set :webcomic_source_type, :markdown
|
|
16
|
+
app.set :webcomic_uri, "comics"
|
|
17
|
+
app.set :webcomic_template, "/comics/template.html"
|
|
18
|
+
app.set :webcomic_domain, "http://MYSITE.dev" # ?
|
|
19
|
+
|
|
20
|
+
# ???
|
|
21
|
+
app.set :webcomic_enable_stories, false
|
|
22
|
+
app.set :webcomic_story_uri, "story"
|
|
23
|
+
app.set :webcomic_story_template, "/comics/story_template.html"
|
|
24
|
+
|
|
25
|
+
app.set :webcomic_enable_tags, false
|
|
26
|
+
app.set :webcomic_sort_by, :publish_date # or slug? and metadata
|
|
27
|
+
app.set :webcomic_slug_field, :slug
|
|
28
|
+
|
|
29
|
+
app.set :webcomic_include_comic_in_feed, true
|
|
30
|
+
|
|
31
|
+
app.helpers ::Middleman::Features::Webcomic::Helpers
|
|
32
|
+
|
|
33
|
+
app.after_configuration do
|
|
34
|
+
comics, stories= ::Middleman::Webcomic.load_from( File.join(app.root, app.settings.webcomic_source), app )
|
|
35
|
+
|
|
36
|
+
# puts comics.inspect
|
|
37
|
+
|
|
38
|
+
comics.each do |comic|
|
|
39
|
+
#puts "-> #{comic.filename} (#{comic.metadata.inspect})"
|
|
40
|
+
src_path= File.join(app.root, app.settings.webcomic_source_images, comic.filename)
|
|
41
|
+
tgt_path= File.join(app.views, app.settings.webcomic_images, comic.filename)
|
|
42
|
+
|
|
43
|
+
unless File.exists? tgt_path
|
|
44
|
+
if File.exists? src_path
|
|
45
|
+
puts "Moving into place: #{comic.filename}"
|
|
46
|
+
FileUtils.mkdir_p File.dirname(tgt_path), :verbose=>false
|
|
47
|
+
FileUtils.cp src_path, tgt_path, :verbose=>false
|
|
48
|
+
else
|
|
49
|
+
puts "MISSING COMIC: #{comic.filename}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
slug_field= app.settings.webcomic_slug_field
|
|
54
|
+
if File.exists? tgt_path
|
|
55
|
+
#puts "Building: /#{app.settings.webcomic_uri}/#{comic[slug_field]}.html"
|
|
56
|
+
app.page "/#{app.settings.webcomic_uri}/#{comic[slug_field]}.html", :proxy=>app.settings.webcomic_template, :ignore=>true do
|
|
57
|
+
@comic= comic
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
puts "Skipping #{comic.filename} (#{comic[slug_field]})"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
if app.settings.webcomic_enable_stories
|
|
65
|
+
stories.each do |story|
|
|
66
|
+
app.page "/#{app.settings.webcomic_story_uri}/#{story.slug}.html", :proxy=>app.settings.webcomic_story_template, :ignore=>true do
|
|
67
|
+
@story= story
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
app.data_content 'webcomic', {
|
|
73
|
+
:strips=>comics,
|
|
74
|
+
:stories=>stories
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
alias :included :registered
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
module Helpers
|
|
83
|
+
def current_comic
|
|
84
|
+
(@comic || last_comic)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def first_comic
|
|
88
|
+
data.webcomic.strips.last
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def last_comic
|
|
92
|
+
data.webcomic.strips.first
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def next_comic
|
|
96
|
+
current_comic.next
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def prev_comic
|
|
100
|
+
current_comic.prev
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def comic_image_url(comic)
|
|
104
|
+
"/#{settings.webcomic_images}/#{comic.filename}"
|
|
105
|
+
end
|
|
106
|
+
alias :comic_image_for :comic_image_url
|
|
107
|
+
|
|
108
|
+
def current_comic_image
|
|
109
|
+
comic_image_for current_comic
|
|
110
|
+
end
|
|
111
|
+
alias :current_comic_image_url :current_comic_image
|
|
112
|
+
|
|
113
|
+
def comic_path_url(comic)
|
|
114
|
+
"/#{settings.webcomic_uri}/#{comic[settings.webcomic_slug_field]}"
|
|
115
|
+
end
|
|
116
|
+
alias :comic_path_for :comic_path_url
|
|
117
|
+
|
|
118
|
+
def current_comic_path
|
|
119
|
+
comic_path_for current_comic
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def first_comic_path
|
|
123
|
+
comic_path_for first_comic
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def last_comic_path
|
|
127
|
+
comic_path_for last_comic
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def next_comic_path
|
|
131
|
+
comic_path_for next_comic
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def prev_comic_path
|
|
135
|
+
comic_path_for prev_comic
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Story Helpers
|
|
140
|
+
def start_story_path_for(object)
|
|
141
|
+
story = if object.is_a? Story
|
|
142
|
+
object
|
|
143
|
+
else # it's a comic... right?
|
|
144
|
+
data.webcomic.stories.detect {|s| s.title == object.story }
|
|
145
|
+
end
|
|
146
|
+
comic_path_for story.comics.last
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def story_path_for(object)
|
|
150
|
+
story = if object.is_a? Story
|
|
151
|
+
object
|
|
152
|
+
else # it's a comic... right?
|
|
153
|
+
data.webcomic.stories.detect {|s| s.title == object.story }
|
|
154
|
+
end
|
|
155
|
+
"/#{settings.webcomic_story_uri}/#{story.slug}"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Feed Helpers
|
|
159
|
+
|
|
160
|
+
def webcomic_feed_data
|
|
161
|
+
data.webcomic.strips[0...10]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def feed_absolute_paths(source, path=settings.webcomic_domain)
|
|
165
|
+
source.gsub( /src=(["']*)\//) do |match|
|
|
166
|
+
"#{match[0...-1]}#{path}/"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'middleman'
|
|
2
|
+
require 'slim'
|
|
3
|
+
require 'tilt'
|
|
4
|
+
|
|
5
|
+
module Middleman
|
|
6
|
+
module Webcomic
|
|
7
|
+
class MockApp
|
|
8
|
+
|
|
9
|
+
attr_reader :settings
|
|
10
|
+
|
|
11
|
+
def initialize(settings={})
|
|
12
|
+
@settings= ::Thor::CoreExt::HashWithIndifferentAccess.new(settings)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def method_missing(key, value=nil)
|
|
16
|
+
if @settings.has_key? key
|
|
17
|
+
@settings[key]
|
|
18
|
+
elsif @settings.has_key? key.to_s
|
|
19
|
+
@settings[key.to_s]
|
|
20
|
+
else
|
|
21
|
+
#super Should it throw an error?
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parse_front_matter(content)
|
|
27
|
+
Middleman::CoreExtensions::FrontMatter.parse_front_matter(content)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Middleman
|
|
2
|
+
module Webcomic
|
|
3
|
+
class Pager
|
|
4
|
+
attr_reader :all, :pages, :base_url, :current_page, :page_sets
|
|
5
|
+
|
|
6
|
+
def initialize(articles, base_path="/page", page_size=5)
|
|
7
|
+
@all= articles
|
|
8
|
+
@page_size= page_size
|
|
9
|
+
@base_path= base_path
|
|
10
|
+
@page_sets= @all.in_groups_of(page_size, false)
|
|
11
|
+
@pages= []
|
|
12
|
+
@current_page=1
|
|
13
|
+
@page_sets.each do |art_ary|
|
|
14
|
+
@pages << Thor::CoreExt::HashWithIndifferentAccess.new({
|
|
15
|
+
'articles' => art_ary,
|
|
16
|
+
'page' => @current_page,
|
|
17
|
+
'uri' => "#{base_path}/#{current_page}",
|
|
18
|
+
'pager' => self
|
|
19
|
+
})
|
|
20
|
+
@current_page += 1
|
|
21
|
+
end
|
|
22
|
+
@current_page= nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def length
|
|
26
|
+
@pages.length
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def first
|
|
30
|
+
@pages.first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def last
|
|
34
|
+
@pages.last
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def each
|
|
38
|
+
@current_page=1
|
|
39
|
+
@pages.each do |page_set|
|
|
40
|
+
yield page_set
|
|
41
|
+
@current_page += 1
|
|
42
|
+
end
|
|
43
|
+
@current_page= nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def [](key)
|
|
47
|
+
@pages[key]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Rake tasks
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
def ask message
|
|
5
|
+
print message
|
|
6
|
+
STDIN.gets.chomp
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
NOTES_PATH= File.expand_path "./comics/notes" unless defined?(NOTES_PATH)
|
|
10
|
+
IMAGE_PATH= File.expand_path "./comics/images" unless defined?(IMAGE_PATH)
|
|
11
|
+
|
|
12
|
+
namespace :webcomic do
|
|
13
|
+
|
|
14
|
+
desc "Creates a new Comic notes entry from image"
|
|
15
|
+
task :create do
|
|
16
|
+
|
|
17
|
+
require 'yaml'
|
|
18
|
+
require 'date'
|
|
19
|
+
Dir["#{IMAGE_PATH}/*.{jpg,jpe,jpeg,gif,png}"].each do |img_file|
|
|
20
|
+
img_filename = File.basename( img_file )
|
|
21
|
+
basename= img_filename.gsub( File.extname(img_filename), '' )
|
|
22
|
+
note_filename = "#{basename}.comic.markdown"
|
|
23
|
+
path= File.join NOTES_PATH, note_filename
|
|
24
|
+
|
|
25
|
+
unless File.exists? path
|
|
26
|
+
create_notes = ask("Notes for '#{img_filename}' are missing, create? [Yn] ")
|
|
27
|
+
if create_notes.upcase[0] != 'N'
|
|
28
|
+
meta= {
|
|
29
|
+
'title' => basename,
|
|
30
|
+
'slug' => basename,
|
|
31
|
+
'publish_date' => Date.today,
|
|
32
|
+
'filename' => img_filename
|
|
33
|
+
}.to_yaml
|
|
34
|
+
|
|
35
|
+
meta << "---\n\n"
|
|
36
|
+
meta << "\n\n"
|
|
37
|
+
|
|
38
|
+
File.open(path, "w") do |file|
|
|
39
|
+
file.write meta
|
|
40
|
+
end
|
|
41
|
+
puts "Created #{path}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# desc "Validates that there are notes for each image"
|
|
49
|
+
# task :validate do
|
|
50
|
+
# ptus "Coming Soon!"
|
|
51
|
+
# end
|
|
52
|
+
|
|
53
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Settings:
|
|
2
|
+
NOTES_PATH= File.expand_path("./comics/notes")
|
|
3
|
+
IMAGE_PATH= File.expand_path("./comics/images")
|
|
4
|
+
|
|
5
|
+
# For the SYNC task
|
|
6
|
+
SERVER='USERNAME@YOURSITE.COM'
|
|
7
|
+
FOLDER="~/YOURSITE.COM"
|
|
8
|
+
|
|
9
|
+
require 'middleman-webcomic/tasks'
|
|
10
|
+
|
|
11
|
+
desc "Runs server"
|
|
12
|
+
task :server do
|
|
13
|
+
system "middleman server"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "Runs build"
|
|
17
|
+
task :build do
|
|
18
|
+
system "middleman build"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc "Syncs with public server using rsync (if configured)"
|
|
22
|
+
task :sync=>:build do
|
|
23
|
+
cmd= "rsync -avz --delete build/ #{SERVER}:#{FOLDER}"
|
|
24
|
+
puts "Running:\n#{cmd}\n"
|
|
25
|
+
system(cmd)
|
|
26
|
+
puts "Done."
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'middleman'
|
|
5
|
+
|
|
6
|
+
run Middleman.server
|
|
7
|
+
|
|
8
|
+
# Rack config
|
|
9
|
+
|
|
10
|
+
# Look for index files in folders like Apache
|
|
11
|
+
# require "rack/contrib/try_static"
|
|
12
|
+
# use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html', 'index.html', '/index.html']
|
|
13
|
+
|
|
14
|
+
# Cache static assets
|
|
15
|
+
# require "rack/contrib/static_cache"
|
|
16
|
+
# use Rack::StaticCache, :urls => ['/'], :root => 'build'
|