jekyll-paginate-content 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/jekyll-paginate-content.gemspec +1 -1
- data/lib/jekyll/paginate/content.rb +4 -816
- data/lib/jekyll/paginate/content/documentpage.rb +33 -0
- data/lib/jekyll/paginate/content/generator.rb +162 -0
- data/lib/jekyll/paginate/content/pager.rb +72 -0
- data/lib/jekyll/paginate/content/paginator.rb +575 -0
- data/lib/jekyll/paginate/content/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d89fe133d3d6fbeac1388f938042e2bac0b8f2a
|
4
|
+
data.tar.gz: 313b74ec9b559524c714030f0fae8b85bc7b51d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3579a68e5af9f50b240989710bf504538ece3044774122776aa44a9ad99b29cd9ede5554825616aea74d74c18fcf181e064493b92ba32eca91d4c80b0de8c33a
|
7
|
+
data.tar.gz: 2fed90fcfbf04b08d02fdea782dbb0e18f939446124071878ff32257f5f24d01c2f36432554176d7f5ccb0de55206db789b09dd72f62a21c0fb4345df62c3c92
|
data/README.md
CHANGED
@@ -133,6 +133,7 @@ See other [demos](#demos).
|
|
133
133
|
|
134
134
|
## What's new?
|
135
135
|
|
136
|
+
v1.0.3 Bugfixes; force option
|
136
137
|
v1.0.2 Don't regenerate unnecessarily
|
137
138
|
|
138
139
|
## Installation
|
@@ -173,6 +174,8 @@ paginate_content:
|
|
173
174
|
# don't set paginate: true in the front-matter
|
174
175
|
# Default: false
|
175
176
|
|
177
|
+
force: true # Set to true to force regeneration of pages; default: false
|
178
|
+
|
176
179
|
separator: "<!--split-->" # The page separator; default: "<!--page-->"
|
177
180
|
# Can be "h1" to "h6" for automatic splitting
|
178
181
|
# Note: Setext (underline titles) only supports h1 and h2
|
@@ -6,7 +6,7 @@ require "jekyll/paginate/content/version"
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "jekyll-paginate-content"
|
8
8
|
spec.version = Jekyll::Paginate::Content::VERSION
|
9
|
-
spec.required_ruby_version = '>= 2.
|
9
|
+
spec.required_ruby_version = '>= 2.1.0'
|
10
10
|
spec.authors = ["Alex Ibrado"]
|
11
11
|
spec.email = ["alex@ibrado.org"]
|
12
12
|
|
@@ -1,818 +1,6 @@
|
|
1
1
|
require "jekyll/paginate/content/version"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
safe true
|
8
|
-
|
9
|
-
def generate(site)
|
10
|
-
start_time = Time.now
|
11
|
-
|
12
|
-
sconfig = site.config['paginate_content'] || {}
|
13
|
-
|
14
|
-
return unless sconfig["enabled"].nil? || sconfig["enabled"]
|
15
|
-
|
16
|
-
@debug = sconfig["debug"]
|
17
|
-
|
18
|
-
sconfig['collection'] = sconfig['collection'].split(/,\s*/) if sconfig['collection'].is_a?(String)
|
19
|
-
|
20
|
-
collections = [ sconfig['collection'], sconfig["collections"] ].flatten.compact.uniq;
|
21
|
-
collections = [ "posts", "pages" ] if collections.empty?
|
22
|
-
|
23
|
-
# Use this hash syntax to facilite merging _config.yml overrides
|
24
|
-
properties = {
|
25
|
-
'all' => {
|
26
|
-
'autogen' => 'jekyll-paginate-content',
|
27
|
-
'hidden' => true,
|
28
|
-
'tag' => nil,
|
29
|
-
'tags' => nil,
|
30
|
-
'category' => nil,
|
31
|
-
'categories'=> nil
|
32
|
-
},
|
33
|
-
|
34
|
-
'first' => {
|
35
|
-
'hidden' => false,
|
36
|
-
'tag' => '$',
|
37
|
-
'tags' => '$',
|
38
|
-
'category' => '$',
|
39
|
-
'categories'=> '$'
|
40
|
-
},
|
41
|
-
|
42
|
-
'part' => {},
|
43
|
-
|
44
|
-
'last' => {},
|
45
|
-
|
46
|
-
'single' => {}
|
47
|
-
}
|
48
|
-
|
49
|
-
base_url = (sconfig['prepend_baseurl'].nil? || sconfig['prepend_baseurl']) ? site.config['baseurl'] : ''
|
50
|
-
|
51
|
-
@config = {
|
52
|
-
:collections => collections,
|
53
|
-
:title => sconfig['title'],
|
54
|
-
:permalink => sconfig['permalink'] || '/:num/',
|
55
|
-
:trail => sconfig['trail'] || {},
|
56
|
-
:auto => sconfig['auto'],
|
57
|
-
:base_url => base_url,
|
58
|
-
|
59
|
-
:separator => sconfig['separator'] || '<!--page-->',
|
60
|
-
:header => sconfig['header'] || '<!--page_header-->',
|
61
|
-
:footer => sconfig['footer'] || '<!--page_footer-->',
|
62
|
-
|
63
|
-
:single_page => sconfig['single_page'] || '/view-all/',
|
64
|
-
:seo_canonical => sconfig['seo_canonical'].nil? || sconfig['seo_canonical'],
|
65
|
-
:toc_exclude => sconfig['toc_exclude'],
|
66
|
-
|
67
|
-
:properties => properties,
|
68
|
-
:user_props => sconfig['properties'] || {}
|
69
|
-
}
|
70
|
-
|
71
|
-
# Run through each specified collection
|
72
|
-
|
73
|
-
total_skipped = 0
|
74
|
-
|
75
|
-
collections.each do |collection|
|
76
|
-
if collection == "pages"
|
77
|
-
items = site.pages
|
78
|
-
else
|
79
|
-
next if !site.collections.has_key?(collection)
|
80
|
-
items = site.collections[collection].docs
|
81
|
-
end
|
82
|
-
|
83
|
-
new_items = []
|
84
|
-
old_items = []
|
85
|
-
|
86
|
-
total_parts = 0
|
87
|
-
total_copies = 0
|
88
|
-
|
89
|
-
if @config[:auto]
|
90
|
-
if m = /^h(\d)/i.match(@config[:separator])
|
91
|
-
process = items.select { |item| /(\n|)(<h#{m[1]}|-{4,}|={4,})/.match?(item.content) }
|
92
|
-
else
|
93
|
-
process = items.select { |item| item.content.include?(@config[:separator]) }
|
94
|
-
end
|
95
|
-
else
|
96
|
-
process = items.select { |item| item.data['paginate'] }
|
97
|
-
end
|
98
|
-
|
99
|
-
process.each do |item|
|
100
|
-
paginator = Paginator.new(site, collection, item, @config)
|
101
|
-
if paginator.skipped
|
102
|
-
debug "[#{collection}] \"#{item.data['title']}\" skipped"
|
103
|
-
total_skipped += 1
|
104
|
-
end
|
105
|
-
|
106
|
-
next if paginator.items.empty?
|
107
|
-
|
108
|
-
debug "[#{collection}] \"#{item.data['title']}\", #{paginator.items.length-1}+1 pages"
|
109
|
-
total_parts += paginator.items.length-1;
|
110
|
-
total_copies += 1
|
111
|
-
new_items << paginator.items
|
112
|
-
old_items << item
|
113
|
-
end
|
114
|
-
|
115
|
-
if !new_items.empty?
|
116
|
-
# Remove the old items at the original URLs
|
117
|
-
old_items.each do |item|
|
118
|
-
items.delete(item)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Add the new items in
|
122
|
-
new_items.flatten!.each do |new_item|
|
123
|
-
items << new_item
|
124
|
-
end
|
125
|
-
|
126
|
-
info "[#{collection}] Generated #{total_parts}+#{total_copies} pages"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
if total_skipped > 0
|
131
|
-
s = (total_skipped == 1 ? '' : 's')
|
132
|
-
info "Skipped #{total_skipped} unchanged item#{s}"
|
133
|
-
end
|
134
|
-
|
135
|
-
runtime = "%.6f" % (Time.now - start_time).to_f
|
136
|
-
debug "Runtime: #{runtime}s"
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
def info(msg)
|
141
|
-
Jekyll.logger.info "PaginateContent:", msg
|
142
|
-
end
|
143
|
-
|
144
|
-
def warn(msg)
|
145
|
-
Jekyll.logger.warn "PaginateContent:", msg
|
146
|
-
end
|
147
|
-
|
148
|
-
def debug(msg)
|
149
|
-
Jekyll.logger.warn "PaginateContent:", msg if @debug
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
class Document < Jekyll::Document
|
154
|
-
attr_accessor :pager
|
155
|
-
|
156
|
-
def initialize(orig_doc, site, collection)
|
157
|
-
super(orig_doc.path, { :site => site,
|
158
|
-
:collection => site.collections[collection]})
|
159
|
-
self.merge_data!(orig_doc.data)
|
160
|
-
end
|
161
|
-
|
162
|
-
def data
|
163
|
-
@data ||= {}
|
164
|
-
end
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
class Page < Jekyll::Page
|
169
|
-
def initialize(orig_page, site, dirname, filename)
|
170
|
-
@site = site
|
171
|
-
@base = site.source
|
172
|
-
@dir = dirname
|
173
|
-
@name = filename
|
174
|
-
|
175
|
-
self.process(filename)
|
176
|
-
self.data ||= {}
|
177
|
-
self.data.merge!(orig_page.data)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
class Pager
|
182
|
-
attr_accessor :activated, :first_page, :first_page_path,
|
183
|
-
:first_path, :has_next, :has_prev, :has_previous,
|
184
|
-
:is_first, :is_last, :last_page, :last_page_path,
|
185
|
-
:last_path, :next_is_last, :next_page, :next_page_path,
|
186
|
-
:next_path, :next_section, :page, :page_num, :page_path,
|
187
|
-
:page_trail, :pages, :paginated, :previous_is_first,
|
188
|
-
:prev_is_first, :previous_page, :prev_page, :previous_page_path,
|
189
|
-
:previous_path, :prev_path, :prev_section, :previous_section,
|
190
|
-
:section, :seo, :single_page, :toc, :total_pages, :view_all
|
191
|
-
|
192
|
-
def initialize(data)
|
193
|
-
data.each do |k,v|
|
194
|
-
instance_variable_set("@#{k}", v) if self.respond_to? k
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def to_liquid
|
199
|
-
{
|
200
|
-
# Based on sverrir's jpv2
|
201
|
-
'first_page' => first_page,
|
202
|
-
'first_page_path' => first_page_path,
|
203
|
-
'last_page' => last_page,
|
204
|
-
'last_page_path' => last_page_path,
|
205
|
-
'next_page' => next_page,
|
206
|
-
'next_page_path' => next_page_path,
|
207
|
-
'page' => page_num,
|
208
|
-
'page_path' => page_path,
|
209
|
-
'page_trail' => page_trail,
|
210
|
-
'previous_page' => previous_page,
|
211
|
-
'previous_page_path' => previous_page_path,
|
212
|
-
'total_pages' => total_pages, # parts of the original page
|
213
|
-
|
214
|
-
# New stuff
|
215
|
-
'has_next' => has_next,
|
216
|
-
'has_previous' => has_previous,
|
217
|
-
'is_first' => is_first,
|
218
|
-
'is_last' => is_last,
|
219
|
-
'next_is_last' => next_is_last,
|
220
|
-
'previous_is_first' => previous_is_first,
|
221
|
-
'paginated' => paginated,
|
222
|
-
'seo' => seo,
|
223
|
-
'single_page' => single_page,
|
224
|
-
'section' => section,
|
225
|
-
'toc' => toc,
|
226
|
-
'next_section' => next_section,
|
227
|
-
'previous_section' => previous_section,
|
228
|
-
|
229
|
-
# Aliases
|
230
|
-
'activated' => paginated,
|
231
|
-
'first_path' => first_page_path,
|
232
|
-
'next_path' => next_page_path,
|
233
|
-
'has_prev' => has_previous,
|
234
|
-
'previous_path' => previous_page_path,
|
235
|
-
'prev_path' => previous_page_path,
|
236
|
-
'last_path' => last_page_path,
|
237
|
-
'prev_page' => previous_page,
|
238
|
-
'prev_is_first' => previous_is_first,
|
239
|
-
'prev_section' => previous_section,
|
240
|
-
'page_num' => page_num,
|
241
|
-
'pages' => total_pages,
|
242
|
-
'view_all' => single_page
|
243
|
-
}
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
class Paginator
|
248
|
-
attr_accessor :skipped
|
249
|
-
|
250
|
-
def initialize(site, collection, item, config)
|
251
|
-
@site = site
|
252
|
-
@collection = collection
|
253
|
-
@items = []
|
254
|
-
@skipped = false
|
255
|
-
|
256
|
-
source = item.path
|
257
|
-
html = item.destination('')
|
258
|
-
|
259
|
-
if !File.exist?(html) || (File.mtime(html) < File.mtime(source))
|
260
|
-
final_config = {}.merge(config)
|
261
|
-
if item.data.has_key?('paginate_content')
|
262
|
-
item.data['paginate_content'].each do |k,v|
|
263
|
-
s = k.downcase.strip.to_sym
|
264
|
-
final_config[s] = v
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
@config = final_config
|
269
|
-
|
270
|
-
self.split(item)
|
271
|
-
else
|
272
|
-
@skipped = true
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
def items
|
277
|
-
@items
|
278
|
-
end
|
279
|
-
|
280
|
-
def split(item)
|
281
|
-
sep = @config[:separator].downcase.strip
|
282
|
-
|
283
|
-
# Update the header IDs the original document
|
284
|
-
content = item.content
|
285
|
-
|
286
|
-
# Escape special characters inside code blocks
|
287
|
-
content.scan(/(```|~~~+)(.*?)\1/m).each do |e|
|
288
|
-
escaped = e[1].gsub(/([#<\-=])/, '~|\1|')
|
289
|
-
content.gsub!(e[1], escaped)
|
290
|
-
end
|
291
|
-
|
292
|
-
# Generate TOC
|
293
|
-
toc = ""
|
294
|
-
|
295
|
-
seen_anchors = {}
|
296
|
-
list_chars = ['-','*','+']
|
297
|
-
|
298
|
-
if m = /^h([1-6])$/.match(sep)
|
299
|
-
base_level = m[1].to_i - 1
|
300
|
-
else
|
301
|
-
base_level = 5
|
302
|
-
end
|
303
|
-
|
304
|
-
lowest_level = 5
|
305
|
-
|
306
|
-
# TODO: Optimize this regex
|
307
|
-
content.scan(/(^|\r?\n)((#+)\s*([^\r\n#]+)#*\r?\n|([^\r\n]+)\r?\n(=+|\-{4,})\s*\r?\n|<h([1-6])[^>]*>([^\r\n<]+)(\s*<\/h\7>))/mi).each do |m|
|
308
|
-
header = m[3] || m[4] || m[7]
|
309
|
-
|
310
|
-
next if @config[:toc_exclude] && @config[:toc_exclude].include?(header)
|
311
|
-
|
312
|
-
markup = m[1].strip
|
313
|
-
|
314
|
-
# Level is 0-based for convenience
|
315
|
-
if m[3]
|
316
|
-
level = m[2].length - 1
|
317
|
-
elsif m[4]
|
318
|
-
level = m[5][0] == '=' ? 0 : 1
|
319
|
-
elsif m[7]
|
320
|
-
level = m[6].to_i - 1
|
321
|
-
end
|
322
|
-
|
323
|
-
lowest_level = [level, lowest_level].min
|
324
|
-
|
325
|
-
orig_anchor = anchor = header.downcase.gsub(/[[:punct:]]/, '').gsub(/\s+/, '-')
|
326
|
-
|
327
|
-
ctr = 1
|
328
|
-
while seen_anchors[anchor]
|
329
|
-
anchor = "#{orig_anchor}-#{ctr}"
|
330
|
-
ctr += 1
|
331
|
-
end
|
332
|
-
seen_anchors[anchor] = 1
|
333
|
-
|
334
|
-
# Escape the header so we don't match again
|
335
|
-
# for the same header text in a different location
|
336
|
-
escaped = Regexp.escape(markup)
|
337
|
-
markup = "$$_#{markup}_$$"
|
338
|
-
|
339
|
-
content.sub!(/#{escaped}\s*(?=#|\r?\n)/, "#{markup}#{$/}{: id=\"#{anchor}\"}#{$/}")
|
340
|
-
|
341
|
-
# Markdown indent
|
342
|
-
char = list_chars[level % 3]
|
343
|
-
indent = ' ' * level
|
344
|
-
toc << "#{indent}#{char} [#{header}](##{anchor})#{$/}"
|
345
|
-
end
|
346
|
-
|
347
|
-
if lowest_level > 0
|
348
|
-
excess = ' ' * lowest_level
|
349
|
-
toc.gsub!(/^#{excess}/, '')
|
350
|
-
end
|
351
|
-
|
352
|
-
# Restore original header text
|
353
|
-
content.gsub!(/\$\$_(.*?)_\$\$/m, '\1')
|
354
|
-
|
355
|
-
@toc = toc.empty? ? nil : toc
|
356
|
-
|
357
|
-
# Handle splitting by headers, h1-h6
|
358
|
-
if m = /^h([1-6])$/.match(sep)
|
359
|
-
# Split on <h2> etc.
|
360
|
-
|
361
|
-
level = m[1].to_i
|
362
|
-
|
363
|
-
init_pages = []
|
364
|
-
|
365
|
-
# atx syntax: Prefixed by one or more '#'
|
366
|
-
atx = "#" * level
|
367
|
-
atx_parts = content.split(/(?=^#{atx} )/)
|
368
|
-
|
369
|
-
# HTML symtax <h1> to <h6>
|
370
|
-
htx_parts = []
|
371
|
-
atx_parts.each do |section|
|
372
|
-
htx_parts << section.split(/(?=<#{sep}[^>]*>)/i)
|
373
|
-
end
|
374
|
-
htx_parts.flatten!
|
375
|
-
|
376
|
-
if level <= 2
|
377
|
-
# Setext syntax: underlined by '=' (h1) or '-' (h2)
|
378
|
-
# For now require four '-' to avoid confusion with <hr>
|
379
|
-
# or demo YAML front-matter
|
380
|
-
stx = level == 1 ? "=" : '-' * 4
|
381
|
-
htx_parts.each do |section|
|
382
|
-
init_pages << section.split(/(?=^.+\n#{stx}+$)/)
|
383
|
-
end
|
384
|
-
|
385
|
-
else
|
386
|
-
init_pages = htx_parts
|
387
|
-
end
|
388
|
-
|
389
|
-
init_pages.flatten!
|
390
|
-
else
|
391
|
-
init_pages = content.split(sep)
|
392
|
-
end
|
393
|
-
|
394
|
-
return if init_pages.length == 1
|
395
|
-
|
396
|
-
# Unescape special characters inside code blocks, for main content
|
397
|
-
# Main content was modified by adding header IDs
|
398
|
-
content.gsub!(/~\|(.)\|/, '\1')
|
399
|
-
|
400
|
-
# Make page length the minimum, if specified
|
401
|
-
if @config[:minimum]
|
402
|
-
pages = []
|
403
|
-
init_pages.each do |page_content|
|
404
|
-
i = pages.empty? ? 0 : pages.length - 1
|
405
|
-
if !pages[i] || pages[i].length < @config[:minimum]
|
406
|
-
pages[i] ||= ""
|
407
|
-
pages[i] << page_content
|
408
|
-
else
|
409
|
-
pages << page_content
|
410
|
-
i += 1
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
else
|
415
|
-
pages = init_pages
|
416
|
-
end
|
417
|
-
|
418
|
-
page_header = pages[0].split(@config[:header])
|
419
|
-
pages[0] = page_header[1] || page_header[0]
|
420
|
-
header = page_header[1] ? page_header[0] : ''
|
421
|
-
|
422
|
-
page_footer = pages[-1].split(@config[:footer])
|
423
|
-
pages[-1] = page_footer[0]
|
424
|
-
footer = page_footer[1] || ''
|
425
|
-
|
426
|
-
new_items = []
|
427
|
-
page_data = {}
|
428
|
-
|
429
|
-
dirname = ""
|
430
|
-
filename = ""
|
431
|
-
|
432
|
-
# For SEO; 'canonical' is a personal override ;-)
|
433
|
-
site_url = (@site.config['canonical'] || @site.config['url']) + @site.config['baseurl']
|
434
|
-
site_url.gsub!(/\/$/, '')
|
435
|
-
|
436
|
-
# For the permalink
|
437
|
-
base = item.url
|
438
|
-
|
439
|
-
user_props = @config[:user_props]
|
440
|
-
|
441
|
-
first_page_path = ''
|
442
|
-
total_pages = 0
|
443
|
-
single_page = ''
|
444
|
-
id = ("%10.9f" % Time.now.to_f).to_s
|
445
|
-
|
446
|
-
num = 1
|
447
|
-
max = pages.length
|
448
|
-
|
449
|
-
# Find the anchors/targets
|
450
|
-
a_locations = {}
|
451
|
-
i = 1
|
452
|
-
pages.each do |page|
|
453
|
-
# TODO: Optimize this regex
|
454
|
-
page.scan(/<a\s+name=['"](\S+)['"]>[^<]*<\/a>|<[^>]*id=['"](\S+)['"][^>]*>|{:.*id=['"](\S+)['"][^}]*}/i).each do |a|
|
455
|
-
anchor = a[0] || a[1] || a[2]
|
456
|
-
a_locations[anchor] = i
|
457
|
-
end
|
458
|
-
i += 1
|
459
|
-
end
|
460
|
-
|
461
|
-
######################################## Main processing
|
462
|
-
|
463
|
-
pages.each do |page|
|
464
|
-
# Unescape special characters inside code blocks, for pages
|
465
|
-
page.gsub!(/~\|(.)\|/, '\1')
|
466
|
-
|
467
|
-
plink_all = nil
|
468
|
-
plink_next = nil
|
469
|
-
plink_prev = nil
|
470
|
-
|
471
|
-
paginator = {}
|
472
|
-
|
473
|
-
first = num == 1
|
474
|
-
last = num == max
|
475
|
-
|
476
|
-
if m = base.match(/(.*\/[^\.]*)(\.[^\.]+)$/)
|
477
|
-
# /.../filename.ext
|
478
|
-
plink = _permalink(m[1], num, max)
|
479
|
-
plink_all = m[1] + @config[:single_page]
|
480
|
-
plink_prev = _permalink(m[1], num-1, max) if !first
|
481
|
-
plink_next = _permalink(m[1],num+1, max) if !last
|
482
|
-
else
|
483
|
-
# /.../folder/
|
484
|
-
plink = _permalink(base, num, max)
|
485
|
-
plink_all = base + @config[:single_page]
|
486
|
-
plink_prev = _permalink(base, num-1, max) if !first
|
487
|
-
plink_next = _permalink(base, num+1, max) if !last
|
488
|
-
end
|
489
|
-
|
490
|
-
plink_all.gsub!(/\/\//,'/')
|
491
|
-
|
492
|
-
# TODO: Put these in classes
|
493
|
-
|
494
|
-
if @collection == "pages"
|
495
|
-
if first
|
496
|
-
# Keep the info of the original page to avoid warnings
|
497
|
-
# while creating the new virtual pages
|
498
|
-
dirname = File.dirname(plink)
|
499
|
-
filename = item.name
|
500
|
-
page_data = item.data
|
501
|
-
end
|
502
|
-
|
503
|
-
paginator.merge!(page_data)
|
504
|
-
new_part = Page.new(item, @site, dirname, filename)
|
505
|
-
else
|
506
|
-
new_part = Document.new(item, @site, @collection)
|
507
|
-
end
|
508
|
-
|
509
|
-
# Find the section names from the first h1 etc.
|
510
|
-
# TODO: Simplify/merge regex
|
511
|
-
candidates = {}
|
512
|
-
if m = /(.*\r?\n|)#+\s+(.*)\s*#*/.match(page)
|
513
|
-
candidates[m[2]] = m[1].length
|
514
|
-
end
|
515
|
-
|
516
|
-
if m = /(.*\r?\n|)([^\r\n]+)\r?\n(=+|\-{4,})\s*\r?\n/.match(page)
|
517
|
-
candidates[m[2]] = m[1].length
|
518
|
-
end
|
519
|
-
|
520
|
-
if m = /<h([1-6])[^>]*>\s*([^\r\n<]+)(\s*<\/h\1)/mi.match(page)
|
521
|
-
candidates[m[2]] = m[1].length
|
522
|
-
end
|
523
|
-
|
524
|
-
if candidates.empty?
|
525
|
-
section = "Untitled"
|
526
|
-
else
|
527
|
-
section = candidates.sort_by { |k,v| v }.first.flatten[0]
|
528
|
-
end
|
529
|
-
|
530
|
-
paginator['section'] = section
|
531
|
-
|
532
|
-
paginator['paginated'] = true
|
533
|
-
paginator['page_num'] = num
|
534
|
-
paginator['page_path'] = @config[:base_url] + _permalink(base, num, max)
|
535
|
-
|
536
|
-
paginator['first_page'] = 1
|
537
|
-
paginator['first_page_path'] = @config[:base_url] + base
|
538
|
-
|
539
|
-
paginator['last_page'] = pages.length
|
540
|
-
paginator['last_page_path'] = @config[:base_url] + _permalink(base, max, max)
|
541
|
-
|
542
|
-
paginator['total_pages'] = max
|
543
|
-
|
544
|
-
paginator['single_page'] = @config[:base_url] + plink_all
|
545
|
-
|
546
|
-
if first
|
547
|
-
paginator['is_first'] = true
|
548
|
-
first_page_path = @config[:base_url] + base
|
549
|
-
total_pages = max
|
550
|
-
single_page = plink_all
|
551
|
-
else
|
552
|
-
paginator['previous_page'] = num - 1
|
553
|
-
paginator['previous_page_path'] = @config[:base_url] + plink_prev
|
554
|
-
end
|
555
|
-
|
556
|
-
if last
|
557
|
-
paginator['is_last'] = true
|
558
|
-
else
|
559
|
-
paginator['next_page'] = num + 1
|
560
|
-
paginator['next_page_path'] = @config[:base_url] + plink_next
|
561
|
-
end
|
562
|
-
|
563
|
-
paginator['previous_is_first'] = (num == 2)
|
564
|
-
paginator['next_is_last'] = (num == max - 1)
|
565
|
-
|
566
|
-
paginator['has_previous'] = (num >= 2)
|
567
|
-
paginator['has_next'] = (num < max)
|
568
|
-
|
569
|
-
seo = {}
|
570
|
-
seo['canonical'] = _seo('canonical', site_url + plink_all) if @config[:seo_canonical];
|
571
|
-
seo['prev'] = _seo('prev', site_url + plink_prev) if plink_prev
|
572
|
-
seo['next'] = _seo('next', site_url + plink_next) if plink_next
|
573
|
-
seo['links'] = seo.map {|k,v| v }.join($/)
|
574
|
-
|
575
|
-
paginator['seo'] = seo
|
576
|
-
|
577
|
-
# Set the paginator
|
578
|
-
new_part.pager = Pager.new(paginator)
|
579
|
-
|
580
|
-
# Set up the frontmatter properties
|
581
|
-
_set_properties(item, new_part, 'all', user_props)
|
582
|
-
_set_properties(item, new_part, 'first', user_props) if first
|
583
|
-
_set_properties(item, new_part, 'last', user_props) if last
|
584
|
-
_set_properties(item, new_part, 'part', user_props) if !first && !last
|
585
|
-
|
586
|
-
# Don't allow these to be overriden,
|
587
|
-
# i.e. set/reset layout, date, title, permalink
|
588
|
-
|
589
|
-
new_part.data['layout'] = item.data['layout']
|
590
|
-
new_part.data['date'] = item.data['date']
|
591
|
-
new_part.data['permalink'] = plink
|
592
|
-
|
593
|
-
# title is set together with trail below as it may rely on section name
|
594
|
-
|
595
|
-
new_part.data['pagination_info'] =
|
596
|
-
{
|
597
|
-
'curr_page' => num,
|
598
|
-
'total_pages' => max,
|
599
|
-
'type' => first ? 'first' : ( last ? 'last' : 'part'),
|
600
|
-
'id' => id
|
601
|
-
}
|
602
|
-
|
603
|
-
new_part.content = header + page + footer
|
604
|
-
|
605
|
-
new_items << new_part
|
606
|
-
|
607
|
-
num += 1
|
608
|
-
end
|
609
|
-
|
610
|
-
t_config = @config[:trail]
|
611
|
-
t_config[:title] = @config[:title]
|
612
|
-
|
613
|
-
# Replace #target with page_path#target
|
614
|
-
i = 0
|
615
|
-
new_items.each do |item|
|
616
|
-
content = item.content
|
617
|
-
|
618
|
-
_adjust_links(new_items, item.content, a_locations, i+1)
|
619
|
-
|
620
|
-
# Adjust the TOC relative to this page
|
621
|
-
if @toc
|
622
|
-
toc = @toc.dup
|
623
|
-
_adjust_links(new_items, toc, a_locations, i+1)
|
624
|
-
else
|
625
|
-
toc = nil
|
626
|
-
end
|
627
|
-
|
628
|
-
item.pager.toc = { 'simple' => toc }
|
629
|
-
|
630
|
-
item.pager.page_trail = _page_trail(@config[:base_url] + base, new_items, i+1,
|
631
|
-
new_items.length, t_config)
|
632
|
-
|
633
|
-
# Previous/next section name assignments
|
634
|
-
item.pager.previous_section = new_items[i-1].pager.section if i > 0
|
635
|
-
item.pager.next_section = new_items[i+1].pager.section if i < new_items.length - 1
|
636
|
-
|
637
|
-
i += 1
|
638
|
-
end
|
639
|
-
|
640
|
-
# This is in another loop to avoid messing with the titles
|
641
|
-
# during page trail generation
|
642
|
-
i = 1
|
643
|
-
new_items.each do |item|
|
644
|
-
item.data['title'] =
|
645
|
-
_title(@config[:title], new_items, i, new_items.length,
|
646
|
-
@config[:retitle_first])
|
647
|
-
i += 1
|
648
|
-
end
|
649
|
-
|
650
|
-
# Setup single-page view
|
651
|
-
|
652
|
-
if !@config[:single_page].empty?
|
653
|
-
if @collection == "pages"
|
654
|
-
single = Page.new(item, @site, dirname, item.name)
|
655
|
-
else
|
656
|
-
single = Document.new(item, @site, @collection)
|
657
|
-
end
|
658
|
-
|
659
|
-
_set_properties(item, single, 'all', user_props)
|
660
|
-
_set_properties(item, single, 'single', user_props)
|
661
|
-
|
662
|
-
single.data['pagination_info'] = {
|
663
|
-
'type' => 'single',
|
664
|
-
'id' => id
|
665
|
-
}
|
666
|
-
|
667
|
-
# Restore original properties for these
|
668
|
-
single.data['permalink'] = single_page
|
669
|
-
single.data['layout'] = item.data['layout']
|
670
|
-
single.data['date'] = item.data['date']
|
671
|
-
single.data['title'] = item.data['title']
|
672
|
-
|
673
|
-
# Just some limited data for the single page
|
674
|
-
seo = @config[:seo_canonical] ?
|
675
|
-
_seo('canonical', site_url + single_page) : ""
|
676
|
-
|
677
|
-
single_paginator = {
|
678
|
-
'first_page_path' => first_page_path,
|
679
|
-
'total_pages' => total_pages,
|
680
|
-
'toc' => {
|
681
|
-
'simple' => @toc
|
682
|
-
},
|
683
|
-
'seo' => {
|
684
|
-
'links' => seo,
|
685
|
-
'canonical' => seo
|
686
|
-
}
|
687
|
-
}
|
688
|
-
|
689
|
-
single.pager = Pager.new(single_paginator)
|
690
|
-
single.content = item.content
|
691
|
-
|
692
|
-
new_items << single
|
693
|
-
end
|
694
|
-
|
695
|
-
@items = new_items
|
696
|
-
end
|
697
|
-
|
698
|
-
private
|
699
|
-
def _page_trail(base, items, page, max, config)
|
700
|
-
page_trail = []
|
701
|
-
|
702
|
-
before = config["before"] || 0
|
703
|
-
after = config["after"] || 0
|
704
|
-
|
705
|
-
(before <= 0 || before >= max) ? 0 : before
|
706
|
-
(after <= 0 || after >= max) ? 0 : after
|
707
|
-
|
708
|
-
if before.zero? && after.zero?
|
709
|
-
start_page = 1
|
710
|
-
end_page = max
|
711
|
-
else
|
712
|
-
start_page = page - before
|
713
|
-
start_page = 1 if start_page <= 0
|
714
|
-
|
715
|
-
end_page = start_page + before + after
|
716
|
-
if end_page > max
|
717
|
-
end_page = max
|
718
|
-
start_page = max - before - after
|
719
|
-
start_page = 1 if start_page <= 0
|
720
|
-
end
|
721
|
-
end
|
722
|
-
|
723
|
-
i = start_page
|
724
|
-
while i <= end_page do
|
725
|
-
title = _title(config[:title], items, i, max)
|
726
|
-
page_trail <<
|
727
|
-
{
|
728
|
-
'num' => i,
|
729
|
-
'path' => _permalink(base, i, max),
|
730
|
-
'title' => title
|
731
|
-
}
|
732
|
-
i += 1
|
733
|
-
end
|
734
|
-
|
735
|
-
page_trail
|
736
|
-
end
|
737
|
-
|
738
|
-
def _seo(type, url)
|
739
|
-
" <link rel=\"#{type}\" href=\"#{url}\" />"
|
740
|
-
end
|
741
|
-
|
742
|
-
def _permalink(base, page, max)
|
743
|
-
return base if page == 1
|
744
|
-
|
745
|
-
(base + @config[:permalink]).
|
746
|
-
gsub(/:num/, page.to_s).
|
747
|
-
gsub(/:max/, max.to_s).
|
748
|
-
gsub(/\/\//, '/')
|
749
|
-
end
|
750
|
-
|
751
|
-
def _title(format, items, page, max, retitle_first = false)
|
752
|
-
orig = items[page-1].data['title']
|
753
|
-
return orig if !format || (page == 1 && !retitle_first)
|
754
|
-
|
755
|
-
section = items[page-1].pager.section
|
756
|
-
|
757
|
-
format.gsub(/:title/, orig || '').
|
758
|
-
gsub(/:section/, section).
|
759
|
-
gsub(/:num/, page.to_s).
|
760
|
-
gsub(/:max/, max.to_s)
|
761
|
-
end
|
762
|
-
|
763
|
-
def _set_properties(original, item, stage, user_props = nil)
|
764
|
-
stage_props = {}
|
765
|
-
stage_props.merge!(@config[:properties][stage])
|
766
|
-
|
767
|
-
if user_props && user_props.has_key?(stage)
|
768
|
-
stage_props.merge!(user_props[stage])
|
769
|
-
end
|
770
|
-
|
771
|
-
return if stage_props.empty?
|
772
|
-
|
773
|
-
# Handle special values
|
774
|
-
stage_props.delete_if do |k,v|
|
775
|
-
if k == "pagination_info"
|
776
|
-
false
|
777
|
-
elsif v == "/"
|
778
|
-
true
|
779
|
-
else
|
780
|
-
if v.is_a?(String) && m = /\$\.?(.*)$/.match(v)
|
781
|
-
stage_props[k] = m[1].empty? ?
|
782
|
-
original.data[k] : original.data[m[1]]
|
783
|
-
end
|
784
|
-
false
|
785
|
-
end
|
786
|
-
end
|
787
|
-
|
788
|
-
if item.respond_to?('merge_data')
|
789
|
-
item.merge_data!(stage_props)
|
790
|
-
else
|
791
|
-
item.data.merge!(stage_props)
|
792
|
-
end
|
793
|
-
|
794
|
-
end
|
795
|
-
|
796
|
-
def _adjust_links(new_items, content, a_locations, num)
|
797
|
-
# TODO: Try to merge these
|
798
|
-
|
799
|
-
# [Something](#target)
|
800
|
-
content.scan(/\[[^\]]+\]\(#(.*)\)/i).flatten.each do |a|
|
801
|
-
if (page_num = a_locations[a]) && (page_num != num)
|
802
|
-
content.gsub!(/(\[[^\]]+\]\()##{a}(\))/i,
|
803
|
-
'\1' + @site.config['baseurl'] + new_items[page_num-1].data['permalink']+'#'+a+'\2')
|
804
|
-
end
|
805
|
-
end
|
806
|
-
|
807
|
-
# [Something]: #target
|
808
|
-
content.scan(/\[[^\]]+\]:\s*#(\S+)/i).flatten.each do |a|
|
809
|
-
if (page_num = a_locations[a]) && (page_num != num)
|
810
|
-
content.gsub!(/(\[[^\]]+\]:\s*)##{a}/i,
|
811
|
-
'\1' + @site.config['baseurl'] + new_items[page_num-1].data['permalink']+'#'+a)
|
812
|
-
end
|
813
|
-
end
|
814
|
-
|
815
|
-
end
|
816
|
-
end
|
817
|
-
end
|
818
|
-
end
|
3
|
+
require "jekyll/paginate/content/generator"
|
4
|
+
require "jekyll/paginate/content/documentpage"
|
5
|
+
require "jekyll/paginate/content/pager"
|
6
|
+
require "jekyll/paginate/content/paginator"
|