ragerender 0.1.8 → 0.1.9
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/README.rdoc +38 -0
- data/inspector/_templates/comic-page.html +3 -0
- data/lib/ragerender/jekyll/archive.rb +10 -16
- data/lib/ragerender/jekyll/blog.rb +5 -0
- data/lib/ragerender/jekyll/blog_archive.rb +6 -21
- data/lib/ragerender/jekyll/chapter.rb +3 -17
- data/lib/ragerender/jekyll/comics.rb +143 -27
- data/lib/ragerender/jekyll/image.rb +78 -0
- data/lib/ragerender/jekyll/pagination.rb +28 -0
- data/lib/ragerender/jekyll/pipettes.rb +54 -3
- data/lib/ragerender/jekyll/search.rb +68 -13
- data/lib/ragerender/jekyll.rb +0 -3
- metadata +41 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20419a400d4c37d35c8c0aabe8c56f8ffedc814d155c47c5617d2434f1a8e29e
|
|
4
|
+
data.tar.gz: 9286ac86f23882cebb842164276366ddeb00bc5df86b07792bf23951224c8019
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4260db9a06ce8119bcc298b9a0d9c1c570ad3b6f11cae47ba1a53903facfb373d89afa17706285aff94a032af95ce7f6e15d0b19ea061182b42db31d7c29cff8
|
|
7
|
+
data.tar.gz: d3e93dfee30f0a42b19199f9dcaa0a63b236ae8185c6e56b4414f7d3ce271440674740cc3827bb6bdc01a411f7f0bbcbef401c32f8b8455786901d46cf970a4a
|
data/README.rdoc
CHANGED
|
@@ -209,6 +209,44 @@ You control this by setting a <tt>frontpage</tt> key in your site config.
|
|
|
209
209
|
- anything else will display the extra page that has the matching
|
|
210
210
|
<tt>slug</tt> in its Front Matter
|
|
211
211
|
|
|
212
|
+
=== Comics with custom HTML code
|
|
213
|
+
|
|
214
|
+
You can use custom HTML code in place of an image for your comic page. Instead
|
|
215
|
+
of creating an image, just create an HTML file in your <tt>images</tt> folder:
|
|
216
|
+
|
|
217
|
+
cat '<video src="/files/my-animation.webm"></video>" > images/1.html
|
|
218
|
+
|
|
219
|
+
=== Multi-image comics
|
|
220
|
+
|
|
221
|
+
You can add up to 12 images to each comic page on ComicFury. To do that in
|
|
222
|
+
RageRender, add each image to an <tt>images</tt> key in your comic page:
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
title: "Comic with many pages"
|
|
226
|
+
date: "2026-04-20 16:20"
|
|
227
|
+
images:
|
|
228
|
+
- /images/first.png
|
|
229
|
+
- /images/second.png
|
|
230
|
+
- /images/third.png
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
=== Testing search pages
|
|
234
|
+
|
|
235
|
+
Live search does not work in RageRender, as your site is statically built and
|
|
236
|
+
can't respond to new data from the browser. However, you can simulate a search
|
|
237
|
+
when you build the site to help test search results designs. To do that, add a
|
|
238
|
+
`searchterm` to the search page using defaults in your `_config.yml`:
|
|
239
|
+
|
|
240
|
+
defaults:
|
|
241
|
+
- scope:
|
|
242
|
+
path: ''
|
|
243
|
+
layout: search
|
|
244
|
+
values:
|
|
245
|
+
searchterm: "my character"
|
|
246
|
+
|
|
247
|
+
The search that gets performed will be somewhat similar to how ComicFury will
|
|
248
|
+
search your comic, but may not be exactly the same.
|
|
249
|
+
|
|
212
250
|
=== Putting changes on ComicFury
|
|
213
251
|
|
|
214
252
|
Once you're done making changes, you can <tt>pack</tt> your layout:
|
|
@@ -125,34 +125,28 @@ module RageRender
|
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
def_loop :comics_paginated,
|
|
128
|
+
def_loop :comics_paginated, *PaginatedComicDrop.own_methods
|
|
129
129
|
def comics_paginated
|
|
130
130
|
number = @obj.data['number']
|
|
131
131
|
comics = if number
|
|
132
132
|
selected_comics.to_a[number - 1]
|
|
133
133
|
else
|
|
134
134
|
selected_comics.to_a.flatten
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
comics.map do |
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
drop = ComicDrop.new(comic)
|
|
141
|
-
{
|
|
142
|
-
**ComicDrop::PAGINATION_FIELDS.map {|field| [field, drop[field]] }.to_h,
|
|
143
|
-
**ChapterDrop::PAGINATION_FIELDS.map {|field| [field, chapter_data[field]] }.to_h,
|
|
144
|
-
'number' => index + 1,
|
|
145
|
-
'newchapter' => index == 0,
|
|
146
|
-
'chapterend' => index == comics.size - 1,
|
|
147
|
-
}
|
|
148
|
-
end
|
|
149
|
-
end.flatten
|
|
135
|
+
end || []
|
|
136
|
+
|
|
137
|
+
comics.map do |comic|
|
|
138
|
+
PaginatedComicDrop.new(comic, comics)
|
|
139
|
+
end
|
|
150
140
|
end
|
|
151
141
|
|
|
152
142
|
def lastpagenumber
|
|
153
143
|
selected_comics.size
|
|
154
144
|
end
|
|
155
145
|
|
|
146
|
+
def thumbnail_box_styles
|
|
147
|
+
'position:fixed; opacity:0; pointer-events:none; z-index:10000;'
|
|
148
|
+
end
|
|
149
|
+
|
|
156
150
|
private
|
|
157
151
|
def selected_comics
|
|
158
152
|
comics = @obj.site.collections['comics'].docs.reject {|c| SPECIAL_COMIC_SLUGS.include? c.data['slug'] }
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
require 'jekyll/hooks'
|
|
2
2
|
require 'jekyll/drops/document_drop'
|
|
3
3
|
require_relative '../date_formats'
|
|
4
|
+
require_relative 'setup_collection'
|
|
4
5
|
require_relative 'pipettes'
|
|
5
6
|
|
|
7
|
+
Jekyll::Hooks.register :site, :after_init do |site|
|
|
8
|
+
setup_collection site, :posts, '/blogarchive/:slug/', layout: 'blog-display'
|
|
9
|
+
end
|
|
10
|
+
|
|
6
11
|
Jekyll::Hooks.register :posts, :pre_render do |post, payload|
|
|
7
12
|
RageRender::Pipettes.clean_payload payload
|
|
8
13
|
payload.merge! RageRender::BlogDrop.new(post).to_liquid
|
|
@@ -90,31 +90,16 @@ module RageRender
|
|
|
90
90
|
all_blogs[number-1]&.map {|blog| PaginatedBlogDrop.new(blog).to_liquid } || []
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
all_blogs.size
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Objects used for laying out page numbers.
|
|
98
|
-
#
|
|
99
|
-
# The page numbers always include:
|
|
100
|
-
# - the first page
|
|
101
|
-
# - the last page
|
|
102
|
-
# - two pages around the current page
|
|
103
|
-
def pages
|
|
104
|
-
[1].chain([1, all_blogs.size, *(number-2..number+2).to_a].uniq).select {|i| i >= 1 && i <= all_blogs.size }.sort.each_cons(2).map do |prev, page|
|
|
105
|
-
{
|
|
106
|
-
'page' => page,
|
|
107
|
-
'pagelink' => File.join(@obj.url, 'page', page.to_s),
|
|
108
|
-
'is_current' => page == number,
|
|
109
|
-
'skipped_ahead' => page - prev > 1,
|
|
110
|
-
}
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
def_loop :pages, :page, :pagelink, :is_current, :skipped_ahead
|
|
93
|
+
def_pages :all_pages
|
|
114
94
|
|
|
115
95
|
private
|
|
116
96
|
def all_blogs
|
|
117
97
|
@all_blogs = @obj.site.posts.docs.each_slice(BLOGS_PER_PAGE).to_a
|
|
118
98
|
end
|
|
99
|
+
|
|
100
|
+
def all_pages
|
|
101
|
+
root = Pathname.new(@obj.permalink).split.first.to_s
|
|
102
|
+
@obj.site.pages.select {|page| page.permalink =~ /#{root}\/page/ }
|
|
103
|
+
end
|
|
119
104
|
end
|
|
120
105
|
end
|
|
@@ -74,8 +74,6 @@ module RageRender
|
|
|
74
74
|
COVER_MAX_HEIGHT = 420
|
|
75
75
|
COVER_MAX_WIDTH = 300
|
|
76
76
|
|
|
77
|
-
PAGINATION_FIELDS = %w[ chaptername chapterdescription chapterid ]
|
|
78
|
-
|
|
79
77
|
extend Pipettes
|
|
80
78
|
extend Forwardable
|
|
81
79
|
|
|
@@ -84,7 +82,7 @@ module RageRender
|
|
|
84
82
|
def_delegator :@obj, :url, :chapterarchiveurl
|
|
85
83
|
|
|
86
84
|
def chapterid
|
|
87
|
-
@obj.collection.docs.index @obj
|
|
85
|
+
@obj.collection.docs.sort_by(&:path).index @obj
|
|
88
86
|
end
|
|
89
87
|
|
|
90
88
|
def chaptername
|
|
@@ -92,23 +90,11 @@ module RageRender
|
|
|
92
90
|
end
|
|
93
91
|
|
|
94
92
|
def cover_width_small
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (cover_height.to_f / COVER_MAX_HEIGHT) > (cover_width.to_f / COVER_MAX_WIDTH)
|
|
98
|
-
(cover_height_small * cover_width) / cover_height
|
|
99
|
-
else
|
|
100
|
-
[COVER_MAX_WIDTH, cover_width].min
|
|
101
|
-
end
|
|
93
|
+
scaled_width(cover_width, cover_height, COVER_MAX_WIDTH, COVER_MAX_HEIGHT)
|
|
102
94
|
end
|
|
103
95
|
|
|
104
96
|
def cover_height_small
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (cover_height.to_f / COVER_MAX_HEIGHT) > (cover_width.to_f / COVER_MAX_WIDTH)
|
|
108
|
-
[COVER_MAX_HEIGHT, cover_height].min
|
|
109
|
-
else
|
|
110
|
-
(cover_width_small * cover_height) / cover_width
|
|
111
|
-
end
|
|
97
|
+
scaled_height(cover_width, cover_height, COVER_MAX_WIDTH, COVER_MAX_HEIGHT)
|
|
112
98
|
end
|
|
113
99
|
|
|
114
100
|
def firstcomicinchapter
|
|
@@ -8,8 +8,14 @@ require 'jekyll/drops/drop'
|
|
|
8
8
|
require 'jekyll/drops/document_drop'
|
|
9
9
|
require_relative '../date_formats'
|
|
10
10
|
require_relative 'chapter'
|
|
11
|
+
require_relative 'image'
|
|
12
|
+
require_relative 'setup_collection'
|
|
11
13
|
require_relative 'pipettes'
|
|
12
14
|
|
|
15
|
+
Jekyll::Hooks.register :site, :after_init do |site|
|
|
16
|
+
setup_collection site, :comics, '/:collection/:slug/', layout: 'comic-page', chapter: '0'
|
|
17
|
+
end
|
|
18
|
+
|
|
13
19
|
Jekyll::Hooks.register :comics, :pre_render do |page, payload|
|
|
14
20
|
RageRender::Pipettes.clean_payload payload
|
|
15
21
|
payload.merge! RageRender::ComicDrop.new(page).to_liquid
|
|
@@ -20,16 +26,40 @@ module RageRender
|
|
|
20
26
|
|
|
21
27
|
BASE_DIR = File.join(File.dirname(__FILE__), '..', '..', '..')
|
|
22
28
|
|
|
29
|
+
# If there are any HTML pages in the /images directory, we treat these as
|
|
30
|
+
# HTML-comics where the author has specified their own HTML to use instead of
|
|
31
|
+
# a comic image. We turn these into static files so that they don't appear as
|
|
32
|
+
# extra pages.
|
|
33
|
+
class ComicHTMLToStaticFileGenerator < Jekyll::Generator
|
|
34
|
+
priority :highest
|
|
35
|
+
|
|
36
|
+
def generate site
|
|
37
|
+
site.pages.select {|f| f.relative_path.start_with? 'images' }.each do |html|
|
|
38
|
+
site.pages.delete html
|
|
39
|
+
static_file = Jekyll::StaticFile.new(
|
|
40
|
+
site,
|
|
41
|
+
html.instance_variable_get(:"@base"),
|
|
42
|
+
# Jekyll::Pages have their leading slash removed, but we need it
|
|
43
|
+
html.instance_variable_get(:"@dir").gsub(/^([^\/])/) {|s| '/' + s},
|
|
44
|
+
html.instance_variable_get(:"@name"),
|
|
45
|
+
)
|
|
46
|
+
static_file.data['content'] = html.content
|
|
47
|
+
static_file.defaults['published'] = false
|
|
48
|
+
site.static_files.append static_file
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
23
53
|
# Creates comics for each file found in the 'images' directory
|
|
24
54
|
# that does not already have an associated comic object.
|
|
25
55
|
class ComicFromImageGenerator < Jekyll::Generator
|
|
26
|
-
priority :
|
|
56
|
+
priority :high
|
|
27
57
|
|
|
28
58
|
def generate site
|
|
29
59
|
images = site.static_files.select {|f| f.relative_path.start_with? '/images' }.map {|f| [f.basename, f] }.to_h
|
|
30
60
|
comics = site.collections['comics'].docs.map {|c| [c.basename_without_ext, c] }.to_h
|
|
31
61
|
missing = Set.new(images.keys) - Set.new(comics.keys)
|
|
32
|
-
missing -= Set.new(comics.
|
|
62
|
+
missing -= Set.new(comics.flat_map {|k, c| (c.data['images'] || []) + [c.data['image']] }.reject(&:nil?).map {|img| File.basename(img, '.*') })
|
|
33
63
|
missing.each do |slug|
|
|
34
64
|
comic = Jekyll::Document.new(images[slug].relative_path, site: site, collection: site.collections['comics'])
|
|
35
65
|
comic.send(:merge_defaults)
|
|
@@ -93,16 +123,79 @@ module RageRender
|
|
|
93
123
|
end
|
|
94
124
|
end
|
|
95
125
|
|
|
96
|
-
class
|
|
126
|
+
class PaginatedComicDrop < Jekyll::Drops::DocumentDrop
|
|
97
127
|
extend Pipettes
|
|
98
128
|
|
|
99
|
-
|
|
129
|
+
THUMBNAIL_MAX_HEIGHT = 420
|
|
130
|
+
THUMBNAIL_MAX_WIDTH = 400
|
|
131
|
+
THUMBNAIL_SMALL_MAX_HEIGHT = 210
|
|
132
|
+
THUMBNAIL_SMALL_MAX_WIDTH = 200
|
|
133
|
+
|
|
134
|
+
def initialize obj, all
|
|
135
|
+
super(obj)
|
|
136
|
+
@all = all
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def_delegators :comicdrop, :comicurl, :comictitle, :posttime
|
|
140
|
+
def_safe_delegator :chapterdrop, :chaptername, :chaptername
|
|
141
|
+
def_safe_delegator :chapterdrop, :chapterdescription, :chapterdescription
|
|
142
|
+
def_safe_delegator :chapterdrop, :chapterid, :chapterid
|
|
143
|
+
|
|
144
|
+
def number
|
|
145
|
+
@all.index(@obj) + 1
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def newchapter
|
|
149
|
+
@all.select {|c| c.data['chapter'] == @obj.data['chapter'] }.first == @obj
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def chapterend
|
|
153
|
+
@all.select {|c| c.data['chapter'] == @obj.data['chapter'] }.last == @obj
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def_delegator :comicdrop, :comicimageurl, :thumbnail_url
|
|
157
|
+
|
|
158
|
+
def thumbnail_width
|
|
159
|
+
scaled_width(comicdrop.comicwidth, comicdrop.comicheight, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT) || 0
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def thumbnail_height
|
|
163
|
+
scaled_height(comicdrop.comicwidth, comicdrop.comicheight, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT) || 0
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def thumbnail_width_small
|
|
167
|
+
scaled_width(comicdrop.comicwidth, comicdrop.comicheight, THUMBNAIL_SMALL_MAX_WIDTH, THUMBNAIL_SMALL_MAX_HEIGHT) || 0
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def thumbnail_height_small
|
|
171
|
+
scaled_height(comicdrop.comicwidth, comicdrop.comicheight, THUMBNAIL_SMALL_MAX_WIDTH, THUMBNAIL_SMALL_MAX_HEIGHT) || 0
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
private
|
|
175
|
+
def comicdrop
|
|
176
|
+
@comicdrop ||= ComicDrop.new(@obj)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def chapterdrop
|
|
180
|
+
comicdrop.send(:chapterdrop)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def index
|
|
184
|
+
@index ||= chapterdrop.send(:comics).index(@obj)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
class ComicDrop < Jekyll::Drops::DocumentDrop
|
|
189
|
+
extend Pipettes
|
|
100
190
|
|
|
101
191
|
delegate_method_as :id, :comicid
|
|
102
192
|
def_delegator :@obj, :url, :comicurl
|
|
103
|
-
def_delegator :@obj, :url, :permalink
|
|
104
193
|
data_delegator 'rating'
|
|
105
194
|
data_delegator 'votecount'
|
|
195
|
+
|
|
196
|
+
def permalink
|
|
197
|
+
URI.join(@obj.site.config["url"], @obj.site.baseurl || '/', @obj.url).to_s
|
|
198
|
+
end
|
|
106
199
|
data_delegator 'comments'
|
|
107
200
|
|
|
108
201
|
def comictitle
|
|
@@ -125,10 +218,6 @@ module RageRender
|
|
|
125
218
|
1 + all_comics.index(@obj)
|
|
126
219
|
end
|
|
127
220
|
|
|
128
|
-
def comicsnum
|
|
129
|
-
all_comics.size
|
|
130
|
-
end
|
|
131
|
-
|
|
132
221
|
def posttime
|
|
133
222
|
comicfury_date(@obj.date)
|
|
134
223
|
end
|
|
@@ -250,23 +339,43 @@ module RageRender
|
|
|
250
339
|
end&.url
|
|
251
340
|
end
|
|
252
341
|
|
|
342
|
+
def comicimagetype
|
|
343
|
+
if imagedrops.size > 1
|
|
344
|
+
'multiimage'
|
|
345
|
+
elsif imagedrop.send(:image_obj).extname == '.html'
|
|
346
|
+
'html'
|
|
347
|
+
else
|
|
348
|
+
'image'
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def isimage
|
|
353
|
+
comicimagetype == 'image'
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def_loop :comicparts, *(RageRender::ImageDrop.invokable_methods - Jekyll::Drops::DocumentDrop.invokable_methods)
|
|
357
|
+
def comicparts
|
|
358
|
+
imagedrops.map(&:to_liquid)
|
|
359
|
+
end
|
|
360
|
+
|
|
253
361
|
# An HTML tag to print for the comic image. If there is a future image, then
|
|
254
362
|
# this is also a link to the next comic page.
|
|
255
363
|
def comicimage
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
</a>
|
|
266
|
-
HTML
|
|
267
|
-
[linkopen, image, linkclose].join
|
|
364
|
+
if comicimagetype == 'multiimage'
|
|
365
|
+
<<~HTML
|
|
366
|
+
<div class="comicsegments">
|
|
367
|
+
#{imagedrops.map(&:html).join}
|
|
368
|
+
</div>
|
|
369
|
+
HTML
|
|
370
|
+
else
|
|
371
|
+
imagedrop.html
|
|
372
|
+
end
|
|
268
373
|
end
|
|
269
374
|
|
|
375
|
+
def_safe_delegator :imagedrop, :imageurl, :comicimageurl
|
|
376
|
+
def_safe_delegator :imagedrop, :width, :comicwidth, default=0
|
|
377
|
+
def_safe_delegator :imagedrop, :height, :comicheight, default=0
|
|
378
|
+
|
|
270
379
|
def keys
|
|
271
380
|
super.reject {|k| private_methods.include? k.to_sym }
|
|
272
381
|
end
|
|
@@ -306,13 +415,20 @@ module RageRender
|
|
|
306
415
|
chapter&.next_doc.nil? ? nil : ChapterDrop.new(chapter.next_doc)
|
|
307
416
|
end
|
|
308
417
|
|
|
418
|
+
data_delegator 'images'
|
|
309
419
|
data_delegator 'image'
|
|
310
|
-
def_image_metadata :image
|
|
311
|
-
private :image, :image_url, :image_width, :image_height
|
|
312
420
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
421
|
+
def imagedrops
|
|
422
|
+
paths = (images || []) + [image]
|
|
423
|
+
paths.reject(&:nil?).map do |image|
|
|
424
|
+
relative_path = Pathname.new('/').join(image).to_path
|
|
425
|
+
obj = @obj.site.static_files.detect {|f| f.relative_path == relative_path }
|
|
426
|
+
(paths.size > 1 ? MultiImageDrop : ImageDrop).new(obj, self)
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def imagedrop
|
|
431
|
+
imagedrops.first
|
|
432
|
+
end
|
|
317
433
|
end
|
|
318
434
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'jekyll/drops/drop'
|
|
3
|
+
require_relative 'pipettes'
|
|
4
|
+
|
|
5
|
+
module RageRender
|
|
6
|
+
class ImageDrop < Jekyll::Drops::Drop
|
|
7
|
+
extend Forwardable
|
|
8
|
+
extend Pipettes
|
|
9
|
+
|
|
10
|
+
def initialize(obj, comicdrop)
|
|
11
|
+
super(obj)
|
|
12
|
+
@comic = comicdrop
|
|
13
|
+
@image_obj = obj
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# an <img> tag containing the image, without surrounding link
|
|
17
|
+
def imageonlyhtml
|
|
18
|
+
filehtml || <<~HTML
|
|
19
|
+
<img id="comicimage" src="#{imageurl}" alt="#{comictitle}"
|
|
20
|
+
width="#{width}" height="#{height}"
|
|
21
|
+
title="#{comicdescription}">
|
|
22
|
+
HTML
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# the html contents of this loop iteration. this includes stuff like a
|
|
26
|
+
# surrounding link to the next page
|
|
27
|
+
def html
|
|
28
|
+
filehtml || [
|
|
29
|
+
nextcomic ? "<a href=\"#{nextcomic}\">" : '',
|
|
30
|
+
imageonlyhtml,
|
|
31
|
+
nextcomic ? '</a>' : '',
|
|
32
|
+
].join
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
def image
|
|
37
|
+
@obj.relative_path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def filehtml
|
|
41
|
+
image_obj.data['content']
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def_delegators :@comic, :nextcomic, :comictitle, :comicdescription
|
|
45
|
+
private :nextcomic, :comictitle, :comicdescription
|
|
46
|
+
|
|
47
|
+
def_image_metadata :image
|
|
48
|
+
private :image_url, :image_width, :image_height
|
|
49
|
+
|
|
50
|
+
def imageurl
|
|
51
|
+
image_url unless filehtml
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
alias width image_width
|
|
55
|
+
alias height image_height
|
|
56
|
+
public :imageurl, :width, :height
|
|
57
|
+
|
|
58
|
+
def fallback_data; {}; end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class MultiImageDrop < ImageDrop
|
|
62
|
+
def imageonlyhtml
|
|
63
|
+
<<~HTML
|
|
64
|
+
<img src="#{imageurl}" alt="#{comictitle}"
|
|
65
|
+
width="#{width}" height="#{height}"
|
|
66
|
+
title="#{comicdescription}" class="comicsegmentimage">
|
|
67
|
+
HTML
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def html
|
|
71
|
+
<<~HTML
|
|
72
|
+
<div class="segmentcontainer">
|
|
73
|
+
#{super}
|
|
74
|
+
</div>
|
|
75
|
+
HTML
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require_relative 'pipettes'
|
|
2
|
+
|
|
1
3
|
module RageRender
|
|
2
4
|
module PaginationGenerator
|
|
3
5
|
def handle_page page
|
|
@@ -27,4 +29,30 @@ module RageRender
|
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
class PaginatedPageDrop < Jekyll::Drops::Drop
|
|
34
|
+
extend Pipettes
|
|
35
|
+
|
|
36
|
+
def initialize obj, current_page, prev_page
|
|
37
|
+
super(obj)
|
|
38
|
+
@current = current_page
|
|
39
|
+
@prev = prev_page
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def page
|
|
43
|
+
@obj.data['number']
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def pagelink
|
|
47
|
+
@obj.permalink
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def is_current
|
|
51
|
+
page == @current.data['number']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def skipped_ahead
|
|
55
|
+
page - @prev.data['number'] > 1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
30
58
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Pipettes help you make drops.
|
|
2
2
|
require 'cgi'
|
|
3
3
|
require 'dimensions'
|
|
4
|
+
require 'jekyll/drops/document_drop'
|
|
4
5
|
|
|
5
6
|
module RageRender
|
|
6
7
|
module Pipettes
|
|
@@ -11,9 +12,13 @@ module RageRender
|
|
|
11
12
|
payload.send(:fallback_data).delete_if {|k| methods.include? k}
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
def
|
|
15
|
+
def own_methods
|
|
16
|
+
invokable_methods - Jekyll::Drops::DocumentDrop.invokable_methods
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def def_safe_delegator obj, key, aliaz, default=nil
|
|
15
20
|
define_method(aliaz.to_sym) do
|
|
16
|
-
send(obj.to_sym)&.send(key.to_sym)
|
|
21
|
+
send(obj.to_sym)&.send(key.to_sym) || default
|
|
17
22
|
end
|
|
18
23
|
end
|
|
19
24
|
|
|
@@ -41,6 +46,28 @@ module RageRender
|
|
|
41
46
|
Pathname.new(@obj.path).extname != '.html' ? escape(str) : str
|
|
42
47
|
end
|
|
43
48
|
mod.send(:private, :maybe_escape)
|
|
49
|
+
|
|
50
|
+
mod.define_method(:scaled_width) do |width, height, max_width, max_height|
|
|
51
|
+
return nil if width.nil? || height.zero?
|
|
52
|
+
|
|
53
|
+
if (height.to_f / max_height) > (width.to_f / max_width)
|
|
54
|
+
(scaled_height(width, height, max_width, max_height) * width) / height
|
|
55
|
+
else
|
|
56
|
+
[max_width, width].min
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
mod.send(:private, :scaled_width)
|
|
60
|
+
|
|
61
|
+
mod.define_method(:scaled_height) do |width, height, max_width, max_height|
|
|
62
|
+
return nil if height.nil? || width.zero?
|
|
63
|
+
|
|
64
|
+
if (height.to_f / max_height) > (width.to_f / max_width)
|
|
65
|
+
[max_height, height].min
|
|
66
|
+
else
|
|
67
|
+
(scaled_width(width, height, max_width, max_height) * height) / width
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
mod.send(:private, :scaled_height)
|
|
44
71
|
end
|
|
45
72
|
|
|
46
73
|
def def_image_metadata prefix
|
|
@@ -50,7 +77,8 @@ module RageRender
|
|
|
50
77
|
private :"#{prefix}_relative_path"
|
|
51
78
|
|
|
52
79
|
define_method(:"#{prefix}_url") do
|
|
53
|
-
|
|
80
|
+
site = @obj.instance_variable_get(:"@site") || @obj.send(:site)
|
|
81
|
+
File.join (site.baseurl || ''), send(:"#{prefix}_relative_path")
|
|
54
82
|
end
|
|
55
83
|
|
|
56
84
|
define_method(:"#{prefix}_obj") do
|
|
@@ -74,5 +102,28 @@ module RageRender
|
|
|
74
102
|
send(:"#{prefix}_obj") && (send(:"#{prefix}_obj").data['height'] ||= Dimensions.height(send(:"#{prefix}_path")) rescue nil)
|
|
75
103
|
end
|
|
76
104
|
end
|
|
105
|
+
|
|
106
|
+
def def_pages all_pages
|
|
107
|
+
define_method(:lastpagenumber) do
|
|
108
|
+
send(all_pages).size
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Objects used for laying out page numbers.
|
|
112
|
+
#
|
|
113
|
+
# The page numbers always include:
|
|
114
|
+
# - the first page
|
|
115
|
+
# - the last page
|
|
116
|
+
# - two pages around the current page
|
|
117
|
+
define_method(:pages) do
|
|
118
|
+
pages = send(all_pages)
|
|
119
|
+
[1].chain([1, pages.size, *(number-2..number+2).to_a].uniq).select {|i| i >= 1 && i <= pages.size }.sort.map do |i|
|
|
120
|
+
pages[i-1]
|
|
121
|
+
end.each_cons(2).map do |prev, page|
|
|
122
|
+
PaginatedPageDrop.new(page, @obj, prev)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def_loop :pages, *PaginatedBlogDrop.own_methods
|
|
127
|
+
end
|
|
77
128
|
end
|
|
78
129
|
end
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
require 'jekyll/generator'
|
|
2
|
+
require 'jekyll/drops/drop'
|
|
3
|
+
require_relative 'pagination'
|
|
4
|
+
|
|
1
5
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
2
6
|
if page.data['layout'] == 'search'
|
|
3
7
|
RageRender::Pipettes.clean_payload payload
|
|
@@ -6,36 +10,87 @@ Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
|
6
10
|
end
|
|
7
11
|
|
|
8
12
|
module RageRender
|
|
13
|
+
RESULTS_PER_PAGE = 60
|
|
14
|
+
|
|
15
|
+
class SearchPaginationGenerator < Jekyll::Generator
|
|
16
|
+
priority :low
|
|
17
|
+
|
|
18
|
+
def generate site
|
|
19
|
+
site.pages.select {|p| p.data['layout'] == 'search' }.each do |page|
|
|
20
|
+
SearchPaginator.new(page).generate(site)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class SearchPaginator
|
|
26
|
+
include PaginationGenerator
|
|
27
|
+
|
|
28
|
+
def initialize page
|
|
29
|
+
@page = page
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def source_page site
|
|
33
|
+
@page
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def searchterm
|
|
37
|
+
@page.data['searchterm']
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def num_pages site
|
|
41
|
+
RageRender::search(site, searchterm).each_slice(RESULTS_PER_PAGE).size
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def permalink
|
|
45
|
+
"/search/id/#{searchterm.hash}/:number"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.search site, searchterm
|
|
50
|
+
return [] unless searchterm
|
|
51
|
+
site.collections['comics'].docs.reject {|c| SPECIAL_COMIC_SLUGS.include? c.data['slug'] }.select do |comic|
|
|
52
|
+
[
|
|
53
|
+
*comic.data.fetch('tags', []),
|
|
54
|
+
comic.content,
|
|
55
|
+
*comic.data.fetch('authornotes', []).flat_map {|n| n['comment'] },
|
|
56
|
+
].map(&:downcase).any? {|c| c.include?(searchterm.downcase) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
9
60
|
class SearchDrop < Jekyll::Drops::Drop
|
|
10
61
|
extend Pipettes
|
|
11
62
|
|
|
12
63
|
private delegate_method_as :data, :fallback_data
|
|
13
64
|
data_delegator 'searchterm'
|
|
65
|
+
data_delegator 'number'
|
|
66
|
+
private :number
|
|
14
67
|
|
|
15
68
|
def searched
|
|
16
69
|
!searchterm.nil?
|
|
17
70
|
end
|
|
18
71
|
|
|
19
|
-
def_loop :searchresults,
|
|
72
|
+
def_loop :searchresults, *PaginatedComicDrop.own_methods
|
|
20
73
|
def searchresults
|
|
21
74
|
return [] unless searched
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
comic.content,
|
|
26
|
-
*comic.data.fetch('authornotes', []).flat_map {|n| n['comment'] },
|
|
27
|
-
].map(&:downcase).any? {|c| c.include?(searchterm.downcase) }
|
|
28
|
-
end.map.each_with_index do |comic, index|
|
|
29
|
-
drop = ComicDrop.new(comic)
|
|
30
|
-
{
|
|
31
|
-
'number' => index + 1,
|
|
32
|
-
**ComicDrop::PAGINATION_FIELDS.map {|f| [f.to_s, drop[f]] }.to_h,
|
|
33
|
-
}
|
|
75
|
+
comics = all_results[number-1]
|
|
76
|
+
comics.map do |comic|
|
|
77
|
+
PaginatedComicDrop.new(comic, comics)
|
|
34
78
|
end
|
|
35
79
|
end
|
|
36
80
|
|
|
37
81
|
def foundresults
|
|
38
82
|
searchresults.any?
|
|
39
83
|
end
|
|
84
|
+
|
|
85
|
+
def_pages :all_pages
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
def all_results
|
|
89
|
+
@all_results ||= RageRender::search(@obj.site, searchterm).each_slice(RESULTS_PER_PAGE).to_a
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def all_pages
|
|
93
|
+
@obj.site.pages.select {|p| p.data['searchterm'] == searchterm && p.permalink =~ /id/ }
|
|
94
|
+
end
|
|
40
95
|
end
|
|
41
96
|
end
|
data/lib/ragerender/jekyll.rb
CHANGED
|
@@ -64,9 +64,6 @@ Jekyll::Hooks.register :site, :after_init do |site|
|
|
|
64
64
|
site.config['url'] ||= "https://#{File.basename(site.source)}.thecomicseries.com"
|
|
65
65
|
site.config = site.config
|
|
66
66
|
|
|
67
|
-
setup_collection site, :comics, '/:collection/:slug/', layout: 'comic-page', chapter: '0'
|
|
68
|
-
setup_collection site, :posts, '/blogarchive/:slug/', layout: 'blog-display'
|
|
69
|
-
|
|
70
67
|
site.config['defaults'].push({
|
|
71
68
|
'scope' => {
|
|
72
69
|
'path' => '',
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ragerender
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Simon Worthington
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rsec
|
|
@@ -301,6 +301,44 @@ description: |-
|
|
|
301
301
|
- anything else will display the extra page that has the matching
|
|
302
302
|
<tt>slug</tt> in its Front Matter
|
|
303
303
|
|
|
304
|
+
=== Comics with custom HTML code
|
|
305
|
+
|
|
306
|
+
You can use custom HTML code in place of an image for your comic page. Instead
|
|
307
|
+
of creating an image, just create an HTML file in your <tt>images</tt> folder:
|
|
308
|
+
|
|
309
|
+
cat '<video src="/files/my-animation.webm"></video>" > images/1.html
|
|
310
|
+
|
|
311
|
+
=== Multi-image comics
|
|
312
|
+
|
|
313
|
+
You can add up to 12 images to each comic page on ComicFury. To do that in
|
|
314
|
+
RageRender, add each image to an <tt>images</tt> key in your comic page:
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
title: "Comic with many pages"
|
|
318
|
+
date: "2026-04-20 16:20"
|
|
319
|
+
images:
|
|
320
|
+
- /images/first.png
|
|
321
|
+
- /images/second.png
|
|
322
|
+
- /images/third.png
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
=== Testing search pages
|
|
326
|
+
|
|
327
|
+
Live search does not work in RageRender, as your site is statically built and
|
|
328
|
+
can't respond to new data from the browser. However, you can simulate a search
|
|
329
|
+
when you build the site to help test search results designs. To do that, add a
|
|
330
|
+
`searchterm` to the search page using defaults in your `_config.yml`:
|
|
331
|
+
|
|
332
|
+
defaults:
|
|
333
|
+
- scope:
|
|
334
|
+
path: ''
|
|
335
|
+
layout: search
|
|
336
|
+
values:
|
|
337
|
+
searchterm: "my character"
|
|
338
|
+
|
|
339
|
+
The search that gets performed will be somewhat similar to how ComicFury will
|
|
340
|
+
search your comic, but may not be exactly the same.
|
|
341
|
+
|
|
304
342
|
=== Putting changes on ComicFury
|
|
305
343
|
|
|
306
344
|
Once you're done making changes, you can <tt>pack</tt> your layout:
|
|
@@ -387,6 +425,7 @@ files:
|
|
|
387
425
|
- lib/ragerender/jekyll/chapter.rb
|
|
388
426
|
- lib/ragerender/jekyll/comics.rb
|
|
389
427
|
- lib/ragerender/jekyll/error.rb
|
|
428
|
+
- lib/ragerender/jekyll/image.rb
|
|
390
429
|
- lib/ragerender/jekyll/overview.rb
|
|
391
430
|
- lib/ragerender/jekyll/pagination.rb
|
|
392
431
|
- lib/ragerender/jekyll/pipettes.rb
|