ragerender 0.1.5 → 0.1.7
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 +23 -11
- data/assets/comic-not-found.html +7 -0
- data/lib/ragerender/cflxml.rb +105 -0
- data/lib/ragerender/jekyll/archive.rb +5 -1
- data/lib/ragerender/jekyll/blog.rb +1 -0
- data/lib/ragerender/jekyll/blog_archive.rb +31 -26
- data/lib/ragerender/jekyll/chapter.rb +14 -20
- data/lib/ragerender/jekyll/comics.rb +50 -1
- data/lib/ragerender/jekyll/error.rb +1 -0
- data/lib/ragerender/jekyll/overview.rb +8 -2
- data/lib/ragerender/jekyll/pipettes.rb +21 -2
- data/lib/ragerender/jekyll/search.rb +4 -0
- data/lib/ragerender/jekyll.rb +62 -5
- metadata +42 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 152c14ba01c06c930b537a0e1c72a994e673fa8aea1176b82f92adfc912e5e77
|
|
4
|
+
data.tar.gz: bfb9fa9e0e5d4e1dae45c3bdc7fc09fd7de45fdcbb3043fd45c26e11404b0d1d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78e6690eb005da5ac9604c4111612b3e3dcf2d68c52bb8b351dc6165d3fecf9acc8267cfb69d551a6ee8374bb6b660d812465e2bb14875e2d95199c5b1a81a6e
|
|
7
|
+
data.tar.gz: 841b860abb04b124f88aa730ece8650fce559f08a889598f4121b503eb6d5c3ef03bb396f6afffe860ded22cffb92d887750cd597b170369dbc74e7660d8f1ea
|
data/README.rdoc
CHANGED
|
@@ -49,7 +49,7 @@ To set up a new site, open a terminal and type:
|
|
|
49
49
|
mkdir mycomic && cd mycomic
|
|
50
50
|
bundle init
|
|
51
51
|
bundle add jekyll
|
|
52
|
-
bundle add ragerender
|
|
52
|
+
bundle add ragerender --group=jekyll_plugins
|
|
53
53
|
|
|
54
54
|
Now you can add comics! Add the image into an <tt>images</tt> folder:
|
|
55
55
|
|
|
@@ -92,6 +92,9 @@ Put something like this in your webcomic folder and call it
|
|
|
92
92
|
description: >
|
|
93
93
|
My epic story about how him and her
|
|
94
94
|
fell into a romantic polycule with they and them
|
|
95
|
+
genres:
|
|
96
|
+
- Comedy
|
|
97
|
+
- Romance
|
|
95
98
|
|
|
96
99
|
defaults:
|
|
97
100
|
- scope:
|
|
@@ -105,18 +108,17 @@ Your webcomic now has its basic information set up.
|
|
|
105
108
|
|
|
106
109
|
=== Adding your layouts
|
|
107
110
|
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
If you want to use your own layout code, then create a <tt>_layouts</tt>
|
|
112
|
+
directory and put the contents of each of your ComicFury layout tabs in there,
|
|
113
|
+
and then put your CSS in the main folder.
|
|
110
114
|
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
The easiest way is to go to your Webcomic Management, click "Edit Layout", then
|
|
116
|
+
in the box labelled "Useful", click "Download Layout Backup". Pass this file to
|
|
117
|
+
RageRender, which will <tt>unpack</tt> it for you:
|
|
113
118
|
|
|
114
|
-
|
|
119
|
+
bundle exec jekyll unpack mycomic-2025-09-13.cflxml
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
directory and put the contents of each of your ComicFury layout tabs in there,
|
|
118
|
-
and then put your CSS in the main folder. You should end up with a full set of
|
|
119
|
-
files like:
|
|
121
|
+
You should end up with a full set of files like:
|
|
120
122
|
|
|
121
123
|
_layouts
|
|
122
124
|
archive.html
|
|
@@ -134,7 +136,7 @@ instead.
|
|
|
134
136
|
|
|
135
137
|
=== Adding blogs
|
|
136
138
|
|
|
137
|
-
Add your blogs into a folder called
|
|
139
|
+
Add your blogs into a folder called <tt>_posts</tt>:
|
|
138
140
|
|
|
139
141
|
cat _posts/2025-05-29-my-new-comic.md
|
|
140
142
|
Hey guys, welcome to my new comic! It's gonna be so sick!
|
|
@@ -201,6 +203,16 @@ You control this by setting a <tt>frontpage</tt> key in your site config.
|
|
|
201
203
|
- anything else will display the extra page that has the matching
|
|
202
204
|
<tt>slug</tt> in its Front Matter
|
|
203
205
|
|
|
206
|
+
=== Putting changes on ComicFury
|
|
207
|
+
|
|
208
|
+
Once you're done making changes, you can <tt>pack</tt> your layout:
|
|
209
|
+
|
|
210
|
+
bundle exec jekyll pack
|
|
211
|
+
|
|
212
|
+
The resulting file can be uploaded to ComicFury by going to your Webcomic
|
|
213
|
+
Management, clicking "Edit Layout", then in the box labelled "Useful", click
|
|
214
|
+
"Restore Layout Backup".
|
|
215
|
+
|
|
204
216
|
=== Stuff that doesn't work
|
|
205
217
|
|
|
206
218
|
Here is a probably incomplete list of things you can expect to be different
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'rexml'
|
|
3
|
+
require 'base64'
|
|
4
|
+
|
|
5
|
+
module RageRender
|
|
6
|
+
HTML_FILES = {
|
|
7
|
+
overall: 'overall',
|
|
8
|
+
overview: 'overview',
|
|
9
|
+
viewblog: 'blog-display',
|
|
10
|
+
comic: 'comic-page',
|
|
11
|
+
archive: 'archive',
|
|
12
|
+
blogarchive: 'blog-archive',
|
|
13
|
+
error: 'error-page',
|
|
14
|
+
search: 'search',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
CSS_FILES = {
|
|
18
|
+
layoutcss: 'layout'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
def self.unpack src, html_dest, css_dest
|
|
22
|
+
doc = REXML::Document.new(src).elements
|
|
23
|
+
html_dir = Pathname.new(html_dest)
|
|
24
|
+
css_dir = Pathname.new(css_dest)
|
|
25
|
+
|
|
26
|
+
HTML_FILES.each do |(tag, filename)|
|
|
27
|
+
File.write html_dir.join(filename + '.html'), Base64.decode64(doc["/layout/ldata/#{tag.to_s}/text()"].value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
CSS_FILES.each do |(tag, filename)|
|
|
31
|
+
File.write css_dir.join(filename + '.css'), Base64.decode64(doc["/layout/ldata/#{tag.to_s}/text()"].value)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.pack html_srcdir, css_srcdir, dest
|
|
36
|
+
layout = REXML::Element.new('layout')
|
|
37
|
+
|
|
38
|
+
name = REXML::Element.new('name')
|
|
39
|
+
name.text = "Downloaded ComicFury layout"
|
|
40
|
+
layout.add name
|
|
41
|
+
|
|
42
|
+
version = REXML::Element.new('cfxml')
|
|
43
|
+
version.text = '1.2'
|
|
44
|
+
layout.add version
|
|
45
|
+
|
|
46
|
+
spage = REXML::Element.new('spage')
|
|
47
|
+
spage.text = '1'
|
|
48
|
+
layout.add spage
|
|
49
|
+
|
|
50
|
+
ldata = REXML::Element.new('ldata')
|
|
51
|
+
html_dir = Pathname.new(html_srcdir)
|
|
52
|
+
css_dir = Pathname.new(css_srcdir)
|
|
53
|
+
|
|
54
|
+
HTML_FILES.each do |(tag, filename)|
|
|
55
|
+
elem = REXML::Element.new tag.to_s
|
|
56
|
+
elem.text = Base64.strict_encode64 File.read html_dir.join(filename + '.html')
|
|
57
|
+
ldata.add elem
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
CSS_FILES.each do |(tag, filename)|
|
|
61
|
+
elem = REXML::Element.new tag.to_s
|
|
62
|
+
elem.text = Base64.strict_encode64 File.read css_dir.join(filename + '.css')
|
|
63
|
+
ldata.add elem
|
|
64
|
+
end
|
|
65
|
+
layout.add ldata
|
|
66
|
+
|
|
67
|
+
# ComicFury will only accept backup files that have:
|
|
68
|
+
# - A valid XML declaration using double quotes
|
|
69
|
+
# – A comment as per below
|
|
70
|
+
# – Tab indentation
|
|
71
|
+
doc = REXML::Document.new(nil, prologue_quote: :quote)
|
|
72
|
+
doc.add REXML::XMLDecl.new REXML::XMLDecl::DEFAULT_VERSION, REXML::XMLDecl::DEFAULT_ENCODING
|
|
73
|
+
doc.add REXML::Comment.new 'This is a ComicFury layout backup, use the import layout function to restore this to a webcomic site. You can access this as follows: Go to your Webcomic Management, click "Edit Layout", then in the Box labelled "Useful", click "Restore Layout Backup"'
|
|
74
|
+
doc.add layout
|
|
75
|
+
|
|
76
|
+
# Pretty print, but *always* make text nodes take up a single line, no
|
|
77
|
+
# matter how long they are
|
|
78
|
+
formatter = REXML::Formatters::Pretty.new(1)
|
|
79
|
+
formatter.compact = true
|
|
80
|
+
formatter.width = Float::INFINITY
|
|
81
|
+
|
|
82
|
+
# Replace the space indentation with tab indentation
|
|
83
|
+
buf = StringIO.new
|
|
84
|
+
formatter.write(doc, buf)
|
|
85
|
+
buf.string.each_line do |line|
|
|
86
|
+
dest << line.gsub(/^ +/) {|sp| "\t" * sp.size }
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if __FILE__ == $0
|
|
92
|
+
case ARGV.shift
|
|
93
|
+
when 'pack'
|
|
94
|
+
html_srcdir, css_srcdir, *dest = ARGV
|
|
95
|
+
RageRender.pack(html_srcdir, css_srcdir, dest.any? ? File.open(dest.first, 'w') : $stdout)
|
|
96
|
+
when 'unpack'
|
|
97
|
+
src, html_dest, css_dest = ARGV
|
|
98
|
+
RageRender.unpack(src == '-' ? $stdin : File.open(src, 'r'), html_dest, css_dest)
|
|
99
|
+
else
|
|
100
|
+
raise <<~USAGE
|
|
101
|
+
Usage: pack html_srcdir css_srcdir dest
|
|
102
|
+
Usage: unpack src html_dest css_dest
|
|
103
|
+
USAGE
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'jekyll/generator'
|
|
2
2
|
require 'jekyll/drops/drop'
|
|
3
3
|
require_relative 'comics'
|
|
4
|
+
require_relative 'chapter'
|
|
4
5
|
require_relative 'pagination'
|
|
5
6
|
require_relative 'pipettes'
|
|
6
7
|
|
|
@@ -8,6 +9,7 @@ require_relative 'pipettes'
|
|
|
8
9
|
# chapter pages because they are not "pages"
|
|
9
10
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
10
11
|
if page.data['layout'] == 'archive'
|
|
12
|
+
RageRender::Pipettes.clean_payload payload
|
|
11
13
|
payload.merge! RageRender::ArchiveDrop.new(page).to_liquid
|
|
12
14
|
end
|
|
13
15
|
end
|
|
@@ -112,6 +114,7 @@ module RageRender
|
|
|
112
114
|
!show_comic_list
|
|
113
115
|
end
|
|
114
116
|
|
|
117
|
+
def_loop :chapters, *(RageRender::ChapterDrop.invokable_methods - Jekyll::Drops::DocumentDrop.invokable_methods)
|
|
115
118
|
def chapters
|
|
116
119
|
unless show_chapter_overview
|
|
117
120
|
@obj.site.collections['chapters'].docs.reject do |page|
|
|
@@ -122,13 +125,14 @@ module RageRender
|
|
|
122
125
|
end
|
|
123
126
|
end
|
|
124
127
|
|
|
128
|
+
def_loop :comics_paginated, :number, :newchapter, :chapterend, *ComicDrop::PAGINATION_FIELDS, *ChapterDrop::PAGINATION_FIELDS
|
|
125
129
|
def comics_paginated
|
|
126
130
|
number = @obj.data['number']
|
|
127
131
|
comics = if number
|
|
128
132
|
selected_comics.to_a[number - 1]
|
|
129
133
|
else
|
|
130
134
|
selected_comics.to_a.flatten
|
|
131
|
-
end
|
|
135
|
+
end&.group_by {|c| c.data['chapter'] } || []
|
|
132
136
|
|
|
133
137
|
comics.map do |chapter, comics|
|
|
134
138
|
chapter_data = ChapterDrop.new(@obj.site.collections['chapters'].docs.detect {|c| c.data['slug'] == chapter })
|
|
@@ -8,6 +8,7 @@ require_relative 'pipettes'
|
|
|
8
8
|
# Pass the right variables to blog archive pages.
|
|
9
9
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
10
10
|
if page.data['layout'] == 'blog-archive'
|
|
11
|
+
RageRender::Pipettes.clean_payload payload
|
|
11
12
|
payload.merge! RageRender::BlogArchiveDrop.new(page).to_liquid
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -51,11 +52,40 @@ module RageRender
|
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
# Data representing a single paginated blog entry, as available from
|
|
56
|
+
# [l:blogs_paginated].
|
|
57
|
+
class PaginatedBlogDrop < Jekyll::Drops::DocumentDrop
|
|
58
|
+
extend Pipettes
|
|
59
|
+
|
|
60
|
+
def_data_delegator :title, :blogtitle
|
|
61
|
+
def_delegator :@obj, :url, :bloglink
|
|
62
|
+
def_data_delegator :author, :authorname
|
|
63
|
+
def_delegator :@obj, :content, :blog
|
|
64
|
+
# TODO profilelink
|
|
65
|
+
|
|
66
|
+
private delegate_method_as :data, :fallback_data
|
|
67
|
+
|
|
68
|
+
def posttime
|
|
69
|
+
comicfury_date(@obj.date)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def allowcomments
|
|
73
|
+
@obj.site.config['allowcomments']
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def comments
|
|
77
|
+
(@obj.data['comments'] || []).size
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
54
81
|
# Data to pass to a blog archive page.
|
|
55
82
|
class BlogArchiveDrop < Jekyll::Drops::Drop
|
|
83
|
+
extend Pipettes
|
|
84
|
+
|
|
56
85
|
private delegate_method_as :data, :fallback_data
|
|
57
86
|
data_delegator 'number'
|
|
58
87
|
|
|
88
|
+
def_loop :blogs_paginated, *(RageRender::PaginatedBlogDrop.invokable_methods - Jekyll::Drops::DocumentDrop.invokable_methods)
|
|
59
89
|
def blogs_paginated
|
|
60
90
|
all_blogs[number-1]&.map {|blog| PaginatedBlogDrop.new(blog).to_liquid } || []
|
|
61
91
|
end
|
|
@@ -80,36 +110,11 @@ module RageRender
|
|
|
80
110
|
}
|
|
81
111
|
end
|
|
82
112
|
end
|
|
113
|
+
def_loop :pages, :page, :pagelink, :is_current, :skipped_ahead
|
|
83
114
|
|
|
84
115
|
private
|
|
85
116
|
def all_blogs
|
|
86
117
|
@all_blogs = @obj.site.posts.docs.each_slice(BLOGS_PER_PAGE).to_a
|
|
87
118
|
end
|
|
88
119
|
end
|
|
89
|
-
|
|
90
|
-
# Data representing a single paginated blog entry, as available from
|
|
91
|
-
# [l:blogs_paginated].
|
|
92
|
-
class PaginatedBlogDrop < Jekyll::Drops::DocumentDrop
|
|
93
|
-
extend Pipettes
|
|
94
|
-
|
|
95
|
-
def_data_delegator :title, :blogtitle
|
|
96
|
-
def_delegator :@obj, :url, :bloglink
|
|
97
|
-
def_data_delegator :author, :authorname
|
|
98
|
-
def_delegator :@obj, :content, :blog
|
|
99
|
-
# TODO profilelink
|
|
100
|
-
|
|
101
|
-
private delegate_method_as :data, :fallback_data
|
|
102
|
-
|
|
103
|
-
def posttime
|
|
104
|
-
comicfury_date(@obj.date)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def allowcomments
|
|
108
|
-
@obj.site.config['allowcomments']
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def comments
|
|
112
|
-
(@obj.data['comments'] || []).size
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
120
|
end
|
|
@@ -21,6 +21,7 @@ Jekyll::Hooks.register :site, :after_init do |site|
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
Jekyll::Hooks.register :chapters, :pre_render do |chapter, payload|
|
|
24
|
+
RageRender::Pipettes.clean_payload payload
|
|
24
25
|
payload.merge! RageRender::ChapterDrop.new(chapter).to_liquid
|
|
25
26
|
payload.merge! RageRender::ArchiveDrop.new(chapter).to_liquid
|
|
26
27
|
end
|
|
@@ -73,21 +74,22 @@ module RageRender
|
|
|
73
74
|
COVER_MAX_HEIGHT = 420
|
|
74
75
|
COVER_MAX_WIDTH = 300
|
|
75
76
|
|
|
76
|
-
PAGINATION_FIELDS = %w[ chaptername chapterdescription ]
|
|
77
|
+
PAGINATION_FIELDS = %w[ chaptername chapterdescription chapterid ]
|
|
77
78
|
|
|
78
79
|
delegate_method_as :data, :fallback_data
|
|
79
80
|
extend Pipettes
|
|
80
81
|
extend Forwardable
|
|
81
82
|
|
|
82
83
|
def_data_delegator :description, :chapterdescription
|
|
84
|
+
def_data_delegator :image, :image
|
|
83
85
|
def_delegator :@obj, :url, :chapterarchiveurl
|
|
84
86
|
|
|
85
|
-
def
|
|
86
|
-
|
|
87
|
+
def chapterid
|
|
88
|
+
@obj.collection.docs.index @obj
|
|
87
89
|
end
|
|
88
90
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
+
def chaptername
|
|
92
|
+
escape @obj.data['title']
|
|
91
93
|
end
|
|
92
94
|
|
|
93
95
|
def cover_width_small
|
|
@@ -117,24 +119,16 @@ module RageRender
|
|
|
117
119
|
end
|
|
118
120
|
|
|
119
121
|
private
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def cover_height
|
|
125
|
-
cover_obj.data['height'] ||= Dimensions.height cover_obj.path
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def cover_obj
|
|
129
|
-
@cover_obj ||= @obj.site.static_files.detect {|f| f.relative_path == cover_relative_path }
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def cover_relative_path
|
|
133
|
-
Pathname.new('/').join(@obj.data['image']).to_s
|
|
134
|
-
end
|
|
122
|
+
def_image_metadata :image
|
|
123
|
+
private :image_url, :image_width, :image_height
|
|
135
124
|
|
|
136
125
|
def first_comic
|
|
137
126
|
@obj.site.collections['comics'].docs.select {|c| c.data['chapter'] == @obj.data['slug'] }.first
|
|
138
127
|
end
|
|
128
|
+
|
|
129
|
+
public
|
|
130
|
+
alias cover image_url
|
|
131
|
+
alias cover_height image_height
|
|
132
|
+
alias cover_width image_width
|
|
139
133
|
end
|
|
140
134
|
end
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'liquid/drop'
|
|
3
|
+
require 'jekyll/hooks'
|
|
4
|
+
require 'jekyll/plugin'
|
|
1
5
|
require 'jekyll/generator'
|
|
2
6
|
require 'jekyll/document'
|
|
7
|
+
require 'jekyll/drops/drop'
|
|
3
8
|
require 'jekyll/drops/document_drop'
|
|
4
9
|
require_relative '../date_formats'
|
|
5
10
|
require_relative 'pipettes'
|
|
6
11
|
|
|
7
12
|
Jekyll::Hooks.register :comics, :pre_render do |page, payload|
|
|
13
|
+
RageRender::Pipettes.clean_payload payload
|
|
8
14
|
payload.merge! RageRender::ComicDrop.new(page).to_liquid
|
|
9
15
|
end
|
|
10
16
|
|
|
11
17
|
module RageRender
|
|
12
18
|
SPECIAL_COMIC_SLUGS = %w{frontpage index}
|
|
13
19
|
|
|
20
|
+
BASE_DIR = File.join(File.dirname(__FILE__), '..', '..', '..')
|
|
21
|
+
|
|
14
22
|
# Creates comics for each file found in the 'images' directory
|
|
15
23
|
# that does not already have an associated comic object.
|
|
16
24
|
class ComicFromImageGenerator < Jekyll::Generator
|
|
@@ -41,9 +49,14 @@ module RageRender
|
|
|
41
49
|
def generate site
|
|
42
50
|
comics = site.collections['comics']
|
|
43
51
|
index = comics.docs.last.dup
|
|
52
|
+
collection = comics.docs
|
|
53
|
+
if index.nil?
|
|
54
|
+
index = site.pages.detect {|p| p.data["title"] == "Comic not found" }.dup
|
|
55
|
+
collection = site.pages
|
|
56
|
+
end
|
|
44
57
|
index.instance_variable_set(:"@data", index.data.dup)
|
|
45
58
|
index.data['slug'] = 'index'
|
|
46
|
-
|
|
59
|
+
collection << index
|
|
47
60
|
end
|
|
48
61
|
end
|
|
49
62
|
|
|
@@ -82,6 +95,7 @@ module RageRender
|
|
|
82
95
|
|
|
83
96
|
delegate_method_as :id, :comicid
|
|
84
97
|
def_delegator :@obj, :url, :comicurl
|
|
98
|
+
def_delegator :@obj, :url, :permalink
|
|
85
99
|
data_delegator 'rating'
|
|
86
100
|
data_delegator 'votecount'
|
|
87
101
|
|
|
@@ -89,10 +103,26 @@ module RageRender
|
|
|
89
103
|
escape @obj.data['title']
|
|
90
104
|
end
|
|
91
105
|
|
|
106
|
+
def comicnumber
|
|
107
|
+
1 + all_comics.index(@obj)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def comicsnum
|
|
111
|
+
all_comics.size
|
|
112
|
+
end
|
|
113
|
+
|
|
92
114
|
def posttime
|
|
93
115
|
comicfury_date(@obj.date)
|
|
94
116
|
end
|
|
95
117
|
|
|
118
|
+
def postyear
|
|
119
|
+
@obj.date.year
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def postmonth
|
|
123
|
+
@obj.date.month
|
|
124
|
+
end
|
|
125
|
+
|
|
96
126
|
def usechapters
|
|
97
127
|
all_comics.any? {|comic| comic.data.include? 'chapter' }
|
|
98
128
|
end
|
|
@@ -109,6 +139,7 @@ module RageRender
|
|
|
109
139
|
chapter&.url
|
|
110
140
|
end
|
|
111
141
|
|
|
142
|
+
def_loop :dropdown, :is_selected, :is_disabled, :title, :grouplabel, :newgroup, :endgroup, :url
|
|
112
143
|
def dropdown
|
|
113
144
|
all_comics.each_with_object([]) do |c, dropdown|
|
|
114
145
|
new_group = dropdown.last.nil? ? true : dropdown.last['grouplabel'] != c.data['chapter']
|
|
@@ -141,6 +172,7 @@ module RageRender
|
|
|
141
172
|
end
|
|
142
173
|
end
|
|
143
174
|
|
|
175
|
+
def_loop :authornotes, :is_reply, :comment, :isguest, :avatar, :authorname, :commentanchor, :posttime, :profilelink
|
|
144
176
|
def authornotes
|
|
145
177
|
@obj.data['authornotes'] || [{
|
|
146
178
|
'is_reply' => false,
|
|
@@ -176,10 +208,22 @@ module RageRender
|
|
|
176
208
|
@obj.previous_doc&.url
|
|
177
209
|
end
|
|
178
210
|
|
|
211
|
+
def prevcomicpermalink
|
|
212
|
+
unless @obj.previous_doc.nil?
|
|
213
|
+
URI.join(@obj.site.config["url"], @obj.site.baseurl || '/', @obj.previous_doc&.url).to_s
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
179
217
|
def nextcomic
|
|
180
218
|
@obj.next_doc&.url
|
|
181
219
|
end
|
|
182
220
|
|
|
221
|
+
def nextcomicpermalink
|
|
222
|
+
unless @obj.next_doc.nil?
|
|
223
|
+
URI.join(@obj.site.config["url"], @obj.site.baseurl || '/', @obj.next_doc&.url).to_s
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
183
227
|
# An HTML tag to print for the comic image. If there is a future image, then
|
|
184
228
|
# this is also a link to the next comic page.
|
|
185
229
|
def comicimage
|
|
@@ -195,6 +239,10 @@ module RageRender
|
|
|
195
239
|
[linkopen, image, linkclose].join
|
|
196
240
|
end
|
|
197
241
|
|
|
242
|
+
def keys
|
|
243
|
+
super.reject {|k| private_methods.include? k.to_sym }
|
|
244
|
+
end
|
|
245
|
+
|
|
198
246
|
def to_liquid
|
|
199
247
|
super.reject do |k, v|
|
|
200
248
|
Jekyll::Drops::DocumentDrop::NESTED_OBJECT_FIELD_BLACKLIST.include? k
|
|
@@ -212,6 +260,7 @@ module RageRender
|
|
|
212
260
|
|
|
213
261
|
data_delegator 'image'
|
|
214
262
|
def_image_metadata :image
|
|
263
|
+
private :image, :image_url, :image_width, :image_height
|
|
215
264
|
|
|
216
265
|
public
|
|
217
266
|
alias comicimageurl image_url
|
|
@@ -6,17 +6,23 @@ require_relative 'blog_archive'
|
|
|
6
6
|
# Pass the right variables to overview pages.
|
|
7
7
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
8
8
|
if page.data['layout'] == 'overview'
|
|
9
|
-
|
|
9
|
+
RageRender::Pipettes.clean_payload payload
|
|
10
|
+
latest_comic = page.site.collections['comics'].docs.last
|
|
11
|
+
if latest_comic
|
|
12
|
+
payload.merge! RageRender::ComicDrop.new(latest_comic).to_liquid
|
|
13
|
+
end
|
|
10
14
|
payload.merge! RageRender::OverviewDrop.new(page).to_liquid
|
|
11
15
|
end
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
module RageRender
|
|
15
19
|
class OverviewDrop < Jekyll::Drops::Drop
|
|
20
|
+
extend Pipettes
|
|
16
21
|
private delegate_method_as :data, :fallback_data
|
|
17
22
|
|
|
23
|
+
def_loop :latestblogs, *(RageRender::PaginatedBlogDrop.invokable_methods - Jekyll::Drops::DocumentDrop.invokable_methods)
|
|
18
24
|
def latestblogs
|
|
19
|
-
@obj.site.posts.docs[-5..]
|
|
25
|
+
@obj.site.posts.docs[-5..]&.map {|post| RageRender::PaginatedBlogDrop.new(post) } || []
|
|
20
26
|
end
|
|
21
27
|
end
|
|
22
28
|
end
|
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
# Pipettes help you make drops.
|
|
2
2
|
require 'cgi'
|
|
3
|
+
require 'dimensions'
|
|
3
4
|
|
|
4
5
|
module RageRender
|
|
5
6
|
module Pipettes
|
|
7
|
+
def self.clean_payload payload
|
|
8
|
+
Jekyll.logger.debug("Cleaning payload")
|
|
9
|
+
sets = Jekyll::Drops::DocumentDrop.subclasses.map(&:invokable_methods)
|
|
10
|
+
methods = sets.reduce(Set.new) {|s,acc| acc.merge(s)} - Set.new(Jekyll::Drops::DocumentDrop.invokable_methods)
|
|
11
|
+
payload.send(:fallback_data).delete_if {|k| methods.include? k}
|
|
12
|
+
end
|
|
13
|
+
|
|
6
14
|
def def_data_delegator key, aliaz
|
|
7
15
|
define_method(aliaz.to_sym) do
|
|
8
16
|
@obj.data[key.to_s]
|
|
9
17
|
end
|
|
10
18
|
end
|
|
11
19
|
|
|
20
|
+
def def_loop method, *fields
|
|
21
|
+
(@loops ||= {})[method.to_sym] = fields
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def loops
|
|
25
|
+
@loops || {}
|
|
26
|
+
end
|
|
27
|
+
|
|
12
28
|
def self.extended mod
|
|
13
29
|
mod.define_method(:escape) do |str|
|
|
14
30
|
str.nil? ? nil : CGI.escapeHTML(str)
|
|
@@ -25,6 +41,7 @@ module RageRender
|
|
|
25
41
|
define_method(:"#{prefix}_relative_path") do
|
|
26
42
|
Pathname.new('/').join(send(prefix.to_sym)).to_path
|
|
27
43
|
end
|
|
44
|
+
private :"#{prefix}_relative_path"
|
|
28
45
|
|
|
29
46
|
define_method(:"#{prefix}_url") do
|
|
30
47
|
File.join (@obj.site.baseurl || ''), send(:"#{prefix}_relative_path")
|
|
@@ -36,17 +53,19 @@ module RageRender
|
|
|
36
53
|
end
|
|
37
54
|
instance_variable_get(:"@#{prefix}_obj")
|
|
38
55
|
end
|
|
56
|
+
private :"#{prefix}_obj"
|
|
39
57
|
|
|
40
58
|
define_method(:"#{prefix}_path") do
|
|
41
59
|
send(:"#{prefix}_obj").path
|
|
42
60
|
end
|
|
61
|
+
private :"#{prefix}_path"
|
|
43
62
|
|
|
44
63
|
define_method(:"#{prefix}_width") do
|
|
45
|
-
send(:"#{prefix}_obj").data['width'] ||= Dimensions.width(send(:"#{prefix}_path")) rescue nil
|
|
64
|
+
send(:"#{prefix}_obj") && (send(:"#{prefix}_obj").data['width'] ||= Dimensions.width(send(:"#{prefix}_path")) rescue nil)
|
|
46
65
|
end
|
|
47
66
|
|
|
48
67
|
define_method(:"#{prefix}_height") do
|
|
49
|
-
send(:"#{prefix}_obj").data['height'] ||= Dimensions.height(send(:"#{prefix}_path")) rescue nil
|
|
68
|
+
send(:"#{prefix}_obj") && (send(:"#{prefix}_obj").data['height'] ||= Dimensions.height(send(:"#{prefix}_path")) rescue nil)
|
|
50
69
|
end
|
|
51
70
|
end
|
|
52
71
|
end
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
2
2
|
if page.data['layout'] == 'search'
|
|
3
|
+
RageRender::Pipettes.clean_payload payload
|
|
3
4
|
payload.merge! RageRender::SearchDrop.new(page).to_liquid
|
|
4
5
|
end
|
|
5
6
|
end
|
|
6
7
|
|
|
7
8
|
module RageRender
|
|
8
9
|
class SearchDrop < Jekyll::Drops::Drop
|
|
10
|
+
extend Pipettes
|
|
11
|
+
|
|
9
12
|
private delegate_method_as :data, :fallback_data
|
|
10
13
|
data_delegator 'searchterm'
|
|
11
14
|
|
|
@@ -13,6 +16,7 @@ module RageRender
|
|
|
13
16
|
!searchterm.nil?
|
|
14
17
|
end
|
|
15
18
|
|
|
19
|
+
def_loop :searchresults, :number, *ComicDrop::PAGINATION_FIELDS
|
|
16
20
|
def searchresults
|
|
17
21
|
return [] unless searched
|
|
18
22
|
@results ||= @obj.site.collections['comics'].docs.select do |comic|
|
data/lib/ragerender/jekyll.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
require 'etc'
|
|
2
2
|
require 'stringio'
|
|
3
|
-
require 'jekyll'
|
|
4
|
-
require '
|
|
3
|
+
require 'jekyll/command'
|
|
4
|
+
require 'jekyll/hooks'
|
|
5
|
+
require 'jekyll/plugin'
|
|
6
|
+
require 'jekyll/generator'
|
|
7
|
+
require 'liquid/drop'
|
|
5
8
|
require_relative 'language'
|
|
6
9
|
require_relative 'functions'
|
|
7
10
|
require_relative 'to_liquid'
|
|
8
11
|
require_relative 'date_formats'
|
|
12
|
+
require_relative 'cflxml'
|
|
9
13
|
require_relative 'jekyll/archive'
|
|
10
14
|
require_relative 'jekyll/blog'
|
|
11
15
|
require_relative 'jekyll/blog_archive'
|
|
@@ -17,6 +21,39 @@ require_relative 'jekyll/search'
|
|
|
17
21
|
require_relative 'jekyll/pipettes'
|
|
18
22
|
require_relative 'jekyll/setup_collection'
|
|
19
23
|
|
|
24
|
+
module RageRender
|
|
25
|
+
class CFLXMLCommands < Jekyll::Command
|
|
26
|
+
class << self
|
|
27
|
+
def init_with_program(jekyll)
|
|
28
|
+
jekyll.command :pack do |pack|
|
|
29
|
+
pack.syntax 'pack'
|
|
30
|
+
pack.description 'Create a ComicFury layout backup from this site'
|
|
31
|
+
pack.action do |args, options|
|
|
32
|
+
config = configuration_from_options(options)
|
|
33
|
+
filename = "#{(config['title'] || File.basename(config['source']))} #{Time.now.to_s}.cflxml"
|
|
34
|
+
puts "Outputting backup file #{filename}"
|
|
35
|
+
File.open(filename, 'w') do |file|
|
|
36
|
+
RageRender.pack config['layouts_dir'], config['source'], file
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
jekyll.command :unpack do |unpack|
|
|
42
|
+
unpack.syntax 'unpack <file>'
|
|
43
|
+
unpack.description 'Overwrite HTML and CSS from a ComicFury layout backup'
|
|
44
|
+
unpack.action do |args, options|
|
|
45
|
+
raise ArgumentError, 'unpack requires one cflxml file' unless args.one?
|
|
46
|
+
config = configuration_from_options(options)
|
|
47
|
+
File.open(args.first, 'r') do |file|
|
|
48
|
+
RageRender.unpack file, config['layouts_dir'], config['source']
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
20
57
|
Jekyll::Hooks.register :site, :after_init do |site|
|
|
21
58
|
# This is obviously quite naughty for many reasons,
|
|
22
59
|
# but it's the only way to get the theme selected
|
|
@@ -24,6 +61,7 @@ Jekyll::Hooks.register :site, :after_init do |site|
|
|
|
24
61
|
site.config['theme'] ||= 'ragerender'
|
|
25
62
|
site.config['title'] ||= File.basename(site.source)
|
|
26
63
|
site.config['search'] ||= true
|
|
64
|
+
site.config['url'] ||= "https://#{File.basename(site.source)}.thecomicseries.com"
|
|
27
65
|
site.config = site.config
|
|
28
66
|
|
|
29
67
|
setup_collection site, :comics, '/:collection/:slug/', layout: 'comic-page', chapter: '0'
|
|
@@ -72,6 +110,10 @@ class RageRender::FrontpageGenerator < Jekyll::Generator
|
|
|
72
110
|
collection = site.pages
|
|
73
111
|
site.pages.detect {|p| p.data["slug"] == frontpage }
|
|
74
112
|
end.dup
|
|
113
|
+
if index.nil?
|
|
114
|
+
collection = site.pages
|
|
115
|
+
index = site.pages.detect {|p| p.data['title'] == 'Comic not found' }.dup
|
|
116
|
+
end
|
|
75
117
|
index.instance_variable_set(:"@data", index.data.dup)
|
|
76
118
|
index.data['permalink'] = '/index.html'
|
|
77
119
|
index.data['slug'] = 'frontpage'
|
|
@@ -84,6 +126,7 @@ Jekyll::Hooks.register :documents, :pre_render do |doc, payload|
|
|
|
84
126
|
end
|
|
85
127
|
|
|
86
128
|
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
|
129
|
+
RageRender::Pipettes.clean_payload payload
|
|
87
130
|
payload.merge! RageRender::WebcomicDrop.new(page).to_liquid
|
|
88
131
|
end
|
|
89
132
|
|
|
@@ -108,6 +151,20 @@ class RageRender::WebcomicDrop < Jekyll::Drops::Drop
|
|
|
108
151
|
escape @obj.site.config['description']
|
|
109
152
|
end
|
|
110
153
|
|
|
154
|
+
def_loop :webcomicgenres, :genre_link, :genre_name
|
|
155
|
+
def webcomicgenres
|
|
156
|
+
(@obj.site.config['genres'] || []).map do |g|
|
|
157
|
+
{
|
|
158
|
+
'genre_name' => escape(g),
|
|
159
|
+
'genre_link' => "https://comicfury.com/search.php?vr=1&query=&tags=#{g.downcase.gsub(/[^a-z]/, '')}"
|
|
160
|
+
}
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def webcomicgenre
|
|
165
|
+
(webcomicgenres.first || {})['genre_name']
|
|
166
|
+
end
|
|
167
|
+
|
|
111
168
|
def webcomicurl
|
|
112
169
|
@obj.site.baseurl
|
|
113
170
|
end
|
|
@@ -117,7 +174,7 @@ class RageRender::WebcomicDrop < Jekyll::Drops::Drop
|
|
|
117
174
|
end
|
|
118
175
|
|
|
119
176
|
def copyrights
|
|
120
|
-
escape @obj.site.config
|
|
177
|
+
escape @obj.site.config.fetch('copyrights', '').gsub('[year]', Date.today.year.to_s)
|
|
121
178
|
end
|
|
122
179
|
|
|
123
180
|
def banner
|
|
@@ -141,6 +198,7 @@ class RageRender::WebcomicDrop < Jekyll::Drops::Drop
|
|
|
141
198
|
false
|
|
142
199
|
end
|
|
143
200
|
|
|
201
|
+
def_loop :extrapages, :link, :title
|
|
144
202
|
def extrapages
|
|
145
203
|
@obj.site.pages.reject {|page| page.data['hidden'] }.map do |page|
|
|
146
204
|
{'link' => page.url, 'title' => escape(page.data['title'])}
|
|
@@ -160,6 +218,7 @@ class RageRender::WebcomicDrop < Jekyll::Drops::Drop
|
|
|
160
218
|
css_files << Pathname.new(@obj.site.theme.includes_path).join('layout.css') unless css_files.any?
|
|
161
219
|
css_files.map {|f| File.read f }.join
|
|
162
220
|
end
|
|
221
|
+
private :css
|
|
163
222
|
|
|
164
223
|
def layoutcss
|
|
165
224
|
<<~HTML
|
|
@@ -169,8 +228,6 @@ class RageRender::WebcomicDrop < Jekyll::Drops::Drop
|
|
|
169
228
|
HTML
|
|
170
229
|
end
|
|
171
230
|
|
|
172
|
-
delegate_method_as :url, :permalink
|
|
173
|
-
|
|
174
231
|
def pagetitle
|
|
175
232
|
escape @obj.data['title']
|
|
176
233
|
end
|
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.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Simon Worthington
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rsec
|
|
@@ -38,6 +38,20 @@ dependencies:
|
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '1.3'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rexml
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: rake
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -127,7 +141,7 @@ description: |-
|
|
|
127
141
|
mkdir mycomic && cd mycomic
|
|
128
142
|
bundle init
|
|
129
143
|
bundle add jekyll
|
|
130
|
-
bundle add ragerender
|
|
144
|
+
bundle add ragerender --group=jekyll_plugins
|
|
131
145
|
|
|
132
146
|
Now you can add comics! Add the image into an <tt>images</tt> folder:
|
|
133
147
|
|
|
@@ -170,6 +184,9 @@ description: |-
|
|
|
170
184
|
description: >
|
|
171
185
|
My epic story about how him and her
|
|
172
186
|
fell into a romantic polycule with they and them
|
|
187
|
+
genres:
|
|
188
|
+
- Comedy
|
|
189
|
+
- Romance
|
|
173
190
|
|
|
174
191
|
defaults:
|
|
175
192
|
- scope:
|
|
@@ -185,8 +202,15 @@ description: |-
|
|
|
185
202
|
|
|
186
203
|
If you want to use your own layout code, then create a <tt>_layouts</tt>
|
|
187
204
|
directory and put the contents of each of your ComicFury layout tabs in there,
|
|
188
|
-
and then put your CSS in the main folder.
|
|
189
|
-
|
|
205
|
+
and then put your CSS in the main folder.
|
|
206
|
+
|
|
207
|
+
The easiest way is to go to your Webcomic Management, click "Edit Layout", then
|
|
208
|
+
in the box labelled "Useful", click "Download Layout Backup". Pass this file to
|
|
209
|
+
RageRender, which will <tt>unpack</tt> it for you:
|
|
210
|
+
|
|
211
|
+
bundle exec jekyll unpack mycomic-2025-09-13.cflxml
|
|
212
|
+
|
|
213
|
+
You should end up with a full set of files like:
|
|
190
214
|
|
|
191
215
|
_layouts
|
|
192
216
|
archive.html
|
|
@@ -204,7 +228,7 @@ description: |-
|
|
|
204
228
|
|
|
205
229
|
=== Adding blogs
|
|
206
230
|
|
|
207
|
-
Add your blogs into a folder called
|
|
231
|
+
Add your blogs into a folder called <tt>_posts</tt>:
|
|
208
232
|
|
|
209
233
|
cat _posts/2025-05-29-my-new-comic.md
|
|
210
234
|
Hey guys, welcome to my new comic! It's gonna be so sick!
|
|
@@ -271,6 +295,16 @@ description: |-
|
|
|
271
295
|
- anything else will display the extra page that has the matching
|
|
272
296
|
<tt>slug</tt> in its Front Matter
|
|
273
297
|
|
|
298
|
+
=== Putting changes on ComicFury
|
|
299
|
+
|
|
300
|
+
Once you're done making changes, you can <tt>pack</tt> your layout:
|
|
301
|
+
|
|
302
|
+
bundle exec jekyll pack
|
|
303
|
+
|
|
304
|
+
The resulting file can be uploaded to ComicFury by going to your Webcomic
|
|
305
|
+
Management, clicking "Edit Layout", then in the box labelled "Useful", click
|
|
306
|
+
"Restore Layout Backup".
|
|
307
|
+
|
|
274
308
|
=== Stuff that doesn't work
|
|
275
309
|
|
|
276
310
|
Here is a probably incomplete list of things you can expect to be different
|
|
@@ -319,9 +353,11 @@ files:
|
|
|
319
353
|
- assets/archive-comics.html
|
|
320
354
|
- assets/archive.html
|
|
321
355
|
- assets/blog.html
|
|
356
|
+
- assets/comic-not-found.html
|
|
322
357
|
- assets/overview.html
|
|
323
358
|
- assets/search.html
|
|
324
359
|
- lib/ragerender.rb
|
|
360
|
+
- lib/ragerender/cflxml.rb
|
|
325
361
|
- lib/ragerender/date_formats.rb
|
|
326
362
|
- lib/ragerender/functions.rb
|
|
327
363
|
- lib/ragerender/jekyll.rb
|