monad 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.markdown +91 -0
  3. data/Gemfile +1 -1
  4. data/History.markdown +772 -0
  5. data/{README.md → README.markdown} +5 -2
  6. data/Rakefile +163 -1
  7. data/bin/monad +86 -30
  8. data/features/create_sites.feature +54 -25
  9. data/features/data.feature +65 -0
  10. data/features/data_sources.feature +10 -10
  11. data/features/drafts.feature +5 -5
  12. data/features/embed_filters.feature +10 -10
  13. data/features/include_tag.feature +48 -0
  14. data/features/markdown.feature +5 -5
  15. data/features/pagination.feature +38 -10
  16. data/features/permalinks.feature +31 -11
  17. data/features/post_data.feature +41 -41
  18. data/features/post_excerpts.feature +50 -0
  19. data/features/site_configuration.feature +47 -26
  20. data/features/site_data.feature +30 -24
  21. data/features/step_definitions/{monad_steps.rb → jekyll_steps.rb} +66 -52
  22. data/features/support/env.rb +27 -8
  23. data/lib/jekyll.rb +99 -0
  24. data/lib/jekyll/cleaner.rb +73 -0
  25. data/lib/{monad → jekyll}/command.rb +6 -6
  26. data/lib/{monad → jekyll}/commands/build.rb +9 -9
  27. data/lib/jekyll/commands/doctor.rb +67 -0
  28. data/lib/jekyll/commands/new.rb +67 -0
  29. data/lib/jekyll/commands/serve.rb +65 -0
  30. data/lib/{monad → jekyll}/configuration.rb +60 -18
  31. data/lib/{monad → jekyll}/converter.rb +1 -1
  32. data/lib/{monad → jekyll}/converters/identity.rb +1 -1
  33. data/lib/{monad → jekyll}/converters/markdown.rb +2 -2
  34. data/lib/jekyll/converters/markdown/kramdown_parser.rb +29 -0
  35. data/lib/{monad → jekyll}/converters/markdown/maruku_parser.rb +12 -8
  36. data/lib/{monad → jekyll}/converters/markdown/rdiscount_parser.rb +4 -2
  37. data/lib/{monad → jekyll}/converters/markdown/redcarpet_parser.rb +1 -1
  38. data/lib/{monad → jekyll}/converters/textile.rb +1 -1
  39. data/lib/{monad → jekyll}/convertible.rb +39 -17
  40. data/lib/{monad → jekyll}/core_ext.rb +22 -4
  41. data/lib/jekyll/deprecator.rb +36 -0
  42. data/lib/{monad → jekyll}/draft.rb +1 -1
  43. data/lib/{monad → jekyll}/drivers/json_driver.rb +1 -1
  44. data/lib/{monad → jekyll}/drivers/yaml_driver.rb +1 -1
  45. data/lib/{monad → jekyll}/errors.rb +1 -1
  46. data/lib/jekyll/excerpt.rb +113 -0
  47. data/lib/{monad → jekyll}/filters.rb +16 -6
  48. data/lib/{monad → jekyll}/generator.rb +1 -1
  49. data/lib/jekyll/generators/pagination.rb +214 -0
  50. data/lib/{monad → jekyll}/layout.rb +4 -1
  51. data/lib/{monad → jekyll}/mime.types +0 -0
  52. data/lib/{monad → jekyll}/page.rb +36 -39
  53. data/lib/{monad → jekyll}/plugin.rb +1 -1
  54. data/lib/{monad → jekyll}/post.rb +58 -123
  55. data/lib/jekyll/related_posts.rb +59 -0
  56. data/lib/{monad → jekyll}/site.rb +120 -123
  57. data/lib/{monad → jekyll}/static_file.rb +1 -1
  58. data/lib/jekyll/stevenson.rb +89 -0
  59. data/lib/jekyll/tags/gist.rb +48 -0
  60. data/lib/{monad → jekyll}/tags/highlight.rb +3 -3
  61. data/lib/jekyll/tags/include.rb +135 -0
  62. data/lib/{monad → jekyll}/tags/post_url.rb +8 -6
  63. data/lib/jekyll/url.rb +67 -0
  64. data/lib/monad.rb +36 -27
  65. data/lib/site_template/_config.yml +2 -1
  66. data/lib/site_template/_layouts/default.html +21 -23
  67. data/lib/site_template/_layouts/post.html +1 -1
  68. data/lib/site_template/_posts/{0000-00-00-welcome-to-monad.markdown.erb → 0000-00-00-welcome-to-jekyll.markdown.erb} +6 -6
  69. data/lib/site_template/css/main.css +22 -27
  70. data/lib/site_template/index.html +2 -2
  71. data/monad.gemspec +153 -52
  72. data/site/.gitignore +4 -0
  73. data/site/CNAME +1 -0
  74. data/site/README +1 -0
  75. data/site/_config.yml +6 -0
  76. data/site/_includes/analytics.html +32 -0
  77. data/site/_includes/docs_contents.html +16 -0
  78. data/site/_includes/docs_contents_mobile.html +23 -0
  79. data/site/_includes/docs_option.html +11 -0
  80. data/site/_includes/docs_ul.html +20 -0
  81. data/site/_includes/footer.html +15 -0
  82. data/site/_includes/header.html +18 -0
  83. data/site/_includes/news_contents.html +23 -0
  84. data/site/_includes/news_contents_mobile.html +11 -0
  85. data/site/_includes/news_item.html +24 -0
  86. data/site/_includes/primary-nav-items.html +14 -0
  87. data/site/_includes/section_nav.html +22 -0
  88. data/site/_includes/top.html +17 -0
  89. data/site/_layouts/default.html +12 -0
  90. data/site/_layouts/docs.html +23 -0
  91. data/site/_layouts/news.html +19 -0
  92. data/site/_layouts/news_item.html +27 -0
  93. data/site/_posts/2013-05-06-jekyll-1-0-0-released.markdown +23 -0
  94. data/site/_posts/2013-05-08-jekyll-1-0-1-released.markdown +27 -0
  95. data/site/_posts/2013-05-12-jekyll-1-0-2-released.markdown +28 -0
  96. data/site/_posts/2013-06-07-jekyll-1-0-3-released.markdown +25 -0
  97. data/site/_posts/2013-07-14-jekyll-1-1-0-released.markdown +27 -0
  98. data/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown +31 -0
  99. data/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown +20 -0
  100. data/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown +20 -0
  101. data/site/_posts/2013-09-06-jekyll-1-2-0-released.markdown +23 -0
  102. data/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown +19 -0
  103. data/site/css/gridism.css +110 -0
  104. data/site/css/normalize.css +1 -0
  105. data/site/css/pygments.css +70 -0
  106. data/site/css/style.css +946 -0
  107. data/site/docs/configuration.md +373 -0
  108. data/site/docs/contributing.md +128 -0
  109. data/site/docs/datafiles.md +63 -0
  110. data/site/docs/deployment-methods.md +109 -0
  111. data/site/docs/drafts.md +20 -0
  112. data/site/docs/extras.md +56 -0
  113. data/site/docs/frontmatter.md +180 -0
  114. data/site/docs/github-pages.md +91 -0
  115. data/site/docs/heroku.md +9 -0
  116. data/site/docs/history.md +722 -0
  117. data/site/docs/index.md +52 -0
  118. data/site/docs/installation.md +76 -0
  119. data/site/docs/migrations.md +257 -0
  120. data/site/docs/pages.md +86 -0
  121. data/site/docs/pagination.md +211 -0
  122. data/site/docs/permalinks.md +180 -0
  123. data/site/docs/plugins.md +508 -0
  124. data/site/docs/posts.md +181 -0
  125. data/site/docs/quickstart.md +32 -0
  126. data/site/docs/resources.md +46 -0
  127. data/site/docs/sites.md +29 -0
  128. data/site/docs/structure.md +190 -0
  129. data/site/docs/templates.md +319 -0
  130. data/site/docs/troubleshooting.md +150 -0
  131. data/site/docs/upgrading.md +146 -0
  132. data/site/docs/usage.md +63 -0
  133. data/site/docs/variables.md +322 -0
  134. data/site/favicon.png +0 -0
  135. data/site/feed.xml +36 -0
  136. data/site/freenode.txt +1 -0
  137. data/site/img/article-footer.png +0 -0
  138. data/site/img/footer-arrow.png +0 -0
  139. data/site/img/footer-logo.png +0 -0
  140. data/site/img/logo-2x.png +0 -0
  141. data/site/img/octojekyll.png +0 -0
  142. data/site/img/tube.png +0 -0
  143. data/site/img/tube1x.png +0 -0
  144. data/site/index.html +90 -0
  145. data/site/js/modernizr-2.5.3.min.js +4 -0
  146. data/site/news/index.html +10 -0
  147. data/site/news/releases/index.html +10 -0
  148. data/test/helper.rb +6 -3
  149. data/test/source/+/foo.md +7 -0
  150. data/test/source/_data/languages.yml +2 -0
  151. data/test/source/_data/members.yaml +7 -0
  152. data/test/source/_data/products.yml +4 -0
  153. data/test/source/_includes/params.html +7 -0
  154. data/test/source/_layouts/default.html +1 -1
  155. data/test/source/_layouts/post/simple.html +1 -0
  156. data/test/source/_plugins/dummy.rb +1 -1
  157. data/test/source/_posts/2013-01-02-post-excerpt.markdown +1 -1
  158. data/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown +23 -0
  159. data/test/source/_posts/2013-08-01-mkdn-extension.mkdn +0 -0
  160. data/test/source/deal.with.dots.html +1 -1
  161. data/test/source/products.yml +4 -0
  162. data/test/test_configuration.rb +46 -11
  163. data/test/test_convertible.rb +2 -2
  164. data/test/test_excerpt.rb +78 -0
  165. data/test/test_filters.rb +4 -4
  166. data/test/test_generated_site.rb +13 -13
  167. data/test/test_json_driver.rb +9 -9
  168. data/test/test_kramdown.rb +32 -5
  169. data/test/test_new_command.rb +8 -8
  170. data/test/test_page.rb +12 -3
  171. data/test/test_pager.rb +34 -33
  172. data/test/test_post.rb +34 -26
  173. data/test/test_redcloth.rb +3 -3
  174. data/test/test_related_posts.rb +47 -0
  175. data/test/test_site.rb +102 -44
  176. data/test/test_tags.rb +168 -23
  177. data/test/test_url.rb +28 -0
  178. data/test/test_yaml_driver.rb +6 -6
  179. metadata +215 -137
  180. data/lib/monad/commands/doctor.rb +0 -29
  181. data/lib/monad/commands/new.rb +0 -50
  182. data/lib/monad/commands/serve.rb +0 -33
  183. data/lib/monad/converters/markdown/kramdown_parser.rb +0 -44
  184. data/lib/monad/deprecator.rb +0 -32
  185. data/lib/monad/generators/pagination.rb +0 -143
  186. data/lib/monad/logger.rb +0 -54
  187. data/lib/monad/tags/gist.rb +0 -30
  188. data/lib/monad/tags/include.rb +0 -37
@@ -0,0 +1,36 @@
1
+ module Jekyll
2
+ class Deprecator
3
+ def self.process(args)
4
+ no_subcommand(args)
5
+ arg_is_present? args, "--server", "The --server command has been replaced by the \
6
+ 'serve' subcommand."
7
+ arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \
8
+ use the 'build' subcommand."
9
+ arg_is_present? args, "--auto", "The switch '--auto' has been replaced with '--watch'."
10
+ arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \
11
+ the '--watch' switch."
12
+ arg_is_present? args, "--pygments", "The 'pygments' setting can only be set in \
13
+ your config files."
14
+ arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in your \
15
+ config files."
16
+ arg_is_present? args, "--url", "The 'url' setting can only be set in your config files."
17
+ end
18
+
19
+ def self.no_subcommand(args)
20
+ if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first)
21
+ Jekyll.logger.error "Deprecation:", "Jekyll now uses subcommands instead of just \
22
+ switches. Run `jekyll help' to find out more."
23
+ end
24
+ end
25
+
26
+ def self.arg_is_present?(args, deprecated_argument, message)
27
+ if args.include?(deprecated_argument)
28
+ deprecation_message(message)
29
+ end
30
+ end
31
+
32
+ def self.deprecation_message(message)
33
+ Jekyll.logger.error "Deprecation:", message
34
+ end
35
+ end
36
+ end
@@ -1,4 +1,4 @@
1
- module Monad
1
+ module Jekyll
2
2
 
3
3
  class Draft < Post
4
4
 
@@ -3,7 +3,7 @@ require 'uri'
3
3
  require 'net/http'
4
4
  require 'net/https' # ruby 1.8.7 requires explicitly require net/https
5
5
 
6
- module Monad
6
+ module Jekyll
7
7
  module Drivers
8
8
  class JsonDriver
9
9
  def initialize(options)
@@ -1,6 +1,6 @@
1
1
  require 'safe_yaml'
2
2
 
3
- module Monad
3
+ module Jekyll
4
4
  module Drivers
5
5
  class YamlDriver
6
6
  def initialize(options)
@@ -1,4 +1,4 @@
1
- module Monad
1
+ module Jekyll
2
2
  class FatalException < StandardError
3
3
  end
4
4
  end
@@ -0,0 +1,113 @@
1
+ module Jekyll
2
+ class Excerpt
3
+ include Convertible
4
+
5
+ attr_accessor :post
6
+ attr_accessor :content, :output, :ext
7
+
8
+ # Initialize this Post instance.
9
+ #
10
+ # site - The Site.
11
+ # base - The String path to the dir containing the post file.
12
+ # name - The String filename of the post file.
13
+ #
14
+ # Returns the new Post.
15
+ def initialize(post)
16
+ self.post = post
17
+ self.content = extract_excerpt(post.content)
18
+ end
19
+
20
+ %w[site name ext].each do |meth|
21
+ define_method(meth) do
22
+ post.send(meth)
23
+ end
24
+ end
25
+
26
+ def to_liquid
27
+ post.to_liquid(Post::EXCERPT_ATTRIBUTES_FOR_LIQUID)
28
+ end
29
+
30
+ # Fetch YAML front-matter data from related post, without layout key
31
+ #
32
+ # Returns Hash of post data
33
+ def data
34
+ @data ||= post.data.dup
35
+ @data.delete("layout")
36
+ @data
37
+ end
38
+
39
+ # 'Path' of the excerpt.
40
+ #
41
+ # Returns the path for the post this excerpt belongs to with #excerpt appended
42
+ def path
43
+ File.join(post.path, "#excerpt")
44
+ end
45
+
46
+ # Check if excerpt includes a string
47
+ #
48
+ # Returns true if the string passed in
49
+ def include?(something)
50
+ (self.output && self.output.include?(something)) || self.content.include?(something)
51
+ end
52
+
53
+ # The UID for this post (useful in feeds).
54
+ # e.g. /2008/11/05/my-awesome-post
55
+ #
56
+ # Returns the String UID.
57
+ def id
58
+ File.join(post.dir, post.slug, "#excerpt")
59
+ end
60
+
61
+ def to_s
62
+ self.output || self.content
63
+ end
64
+
65
+ # Returns the shorthand String identifier of this Post.
66
+ def inspect
67
+ "<Excerpt: #{self.id}>"
68
+ end
69
+
70
+ protected
71
+
72
+ # Internal: Extract excerpt from the content
73
+ #
74
+ # By default excerpt is your first paragraph of a post: everything before
75
+ # the first two new lines:
76
+ #
77
+ # ---
78
+ # title: Example
79
+ # ---
80
+ #
81
+ # First paragraph with [link][1].
82
+ #
83
+ # Second paragraph.
84
+ #
85
+ # [1]: http://example.com/
86
+ #
87
+ # This is fairly good option for Markdown and Textile files. But might cause
88
+ # problems for HTML posts (which is quite unusual for Jekyll). If default
89
+ # excerpt delimiter is not good for you, you might want to set your own via
90
+ # configuration option `excerpt_separator`. For example, following is a good
91
+ # alternative for HTML posts:
92
+ #
93
+ # # file: _config.yml
94
+ # excerpt_separator: "<!-- more -->"
95
+ #
96
+ # Notice that all markdown-style link references will be appended to the
97
+ # excerpt. So the example post above will have this excerpt source:
98
+ #
99
+ # First paragraph with [link][1].
100
+ #
101
+ # [1]: http://example.com/
102
+ #
103
+ # Excerpts are rendered same time as content is rendered.
104
+ #
105
+ # Returns excerpt String
106
+ def extract_excerpt(post_content)
107
+ separator = site.config['excerpt_separator']
108
+ head, _, tail = post_content.partition(separator)
109
+
110
+ "" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
111
+ end
112
+ end
113
+ end
@@ -1,6 +1,6 @@
1
1
  require 'uri'
2
2
 
3
- module Monad
3
+ module Jekyll
4
4
  module Filters
5
5
  # Convert a Textile string into HTML output.
6
6
  #
@@ -9,7 +9,7 @@ module Monad
9
9
  # Returns the HTML formatted String.
10
10
  def textilize(input)
11
11
  site = @context.registers[:site]
12
- converter = site.getConverterImpl(Monad::Converters::Textile)
12
+ converter = site.getConverterImpl(Jekyll::Converters::Textile)
13
13
  converter.convert(input)
14
14
  end
15
15
 
@@ -20,7 +20,7 @@ module Monad
20
20
  # Returns the HTML formatted String.
21
21
  def markdownify(input)
22
22
  site = @context.registers[:site]
23
- converter = site.getConverterImpl(Monad::Converters::Markdown)
23
+ converter = site.getConverterImpl(Jekyll::Converters::Markdown)
24
24
  converter.convert(input)
25
25
  end
26
26
 
@@ -99,7 +99,17 @@ module Monad
99
99
  def cgi_escape(input)
100
100
  CGI::escape(input)
101
101
  end
102
-
102
+
103
+ # URI escape a string.
104
+ #
105
+ # input - The String to escape.
106
+ #
107
+ # Examples
108
+ #
109
+ # uri_escape('foo, bar \\baz?')
110
+ # # => "foo,%20bar%20%5Cbaz?"
111
+ #
112
+ # Returns the escaped String.
103
113
  def uri_escape(input)
104
114
  URI.escape(input)
105
115
  end
@@ -140,7 +150,7 @@ module Monad
140
150
 
141
151
  # Convert the input into json string
142
152
  #
143
- # input - The Array of Hash to be converted
153
+ # input - The Array or Hash to be converted
144
154
  #
145
155
  # Returns the converted json string
146
156
  def json(input)
@@ -155,7 +165,7 @@ module Monad
155
165
  when String
156
166
  Time.parse(input)
157
167
  else
158
- Monad::Logger.error "Invalid Date:", "'#{input}' is not a valid datetime."
168
+ Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime."
159
169
  exit(1)
160
170
  end
161
171
  end
@@ -1,4 +1,4 @@
1
- module Monad
1
+ module Jekyll
2
2
  class Generator < Plugin
3
3
  end
4
4
  end
@@ -0,0 +1,214 @@
1
+ module Jekyll
2
+ module Generators
3
+ class Pagination < Generator
4
+ # This generator is safe from arbitrary code execution.
5
+ safe true
6
+
7
+ # Generate paginated pages if necessary.
8
+ #
9
+ # site - The Site.
10
+ #
11
+ # Returns nothing.
12
+ def generate(site)
13
+ if Pager.pagination_enabled?(site)
14
+ if template = template_page(site)
15
+ paginate(site, template)
16
+ else
17
+ Jekyll.logger.warn "Pagination:", "Pagination is enabled, but I couldn't find" +
18
+ "an index.html page to use as the pagination template. Skipping pagination."
19
+ end
20
+ end
21
+ end
22
+
23
+ # Paginates the blog's posts. Renders the index.html file into paginated
24
+ # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
25
+ # site-wide data.
26
+ #
27
+ # site - The Site.
28
+ # page - The index.html Page that requires pagination.
29
+ #
30
+ # {"paginator" => { "page" => <Number>,
31
+ # "per_page" => <Number>,
32
+ # "posts" => [<Post>],
33
+ # "total_posts" => <Number>,
34
+ # "total_pages" => <Number>,
35
+ # "previous_page" => <Number>,
36
+ # "next_page" => <Number> }}
37
+ def paginate(site, page)
38
+ all_posts = site.site_payload['site']['posts']
39
+ pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i)
40
+ (1..pages).each do |num_page|
41
+ pager = Pager.new(site, num_page, all_posts, pages)
42
+ if num_page > 1
43
+ newpage = Page.new(site, site.source, page.dir, page.name)
44
+ newpage.pager = pager
45
+ newpage.dir = Pager.paginate_path(site, num_page)
46
+ site.pages << newpage
47
+ else
48
+ page.pager = pager
49
+ end
50
+ end
51
+ end
52
+
53
+ # Static: Fetch the URL of the template page. Used to determine the
54
+ # path to the first pager in the series.
55
+ #
56
+ # site - the Jekyll::Site object
57
+ #
58
+ # Returns the url of the template page
59
+ def self.first_page_url(site)
60
+ if page = Pagination.new.template_page(site)
61
+ page.url
62
+ else
63
+ nil
64
+ end
65
+ end
66
+
67
+ # Public: Find the Jekyll::Page which will act as the pager template
68
+ #
69
+ # site - the Jekyll::Site object
70
+ #
71
+ # Returns the Jekyll::Page which will act as the pager template
72
+ def template_page(site)
73
+ site.pages.dup.select do |page|
74
+ Pager.pagination_candidate?(site.config, page)
75
+ end.sort do |one, two|
76
+ two.path.size <=> one.path.size
77
+ end.first
78
+ end
79
+ end
80
+ end
81
+
82
+ class Pager
83
+ attr_reader :page, :per_page, :posts, :total_posts, :total_pages,
84
+ :previous_page, :previous_page_path, :next_page, :next_page_path
85
+
86
+ # Calculate the number of pages.
87
+ #
88
+ # all_posts - The Array of all Posts.
89
+ # per_page - The Integer of entries per page.
90
+ #
91
+ # Returns the Integer number of pages.
92
+ def self.calculate_pages(all_posts, per_page)
93
+ (all_posts.size.to_f / per_page.to_i).ceil
94
+ end
95
+
96
+ # Determine if pagination is enabled the site.
97
+ #
98
+ # site - the Jekyll::Site object
99
+ #
100
+ # Returns true if pagination is enabled, false otherwise.
101
+ def self.pagination_enabled?(site)
102
+ !site.config['paginate'].nil? &&
103
+ site.pages.size > 0
104
+ end
105
+
106
+ # Static: Determine if a page is a possible candidate to be a template page.
107
+ # Page's name must be `index.html` and exist in any of the directories
108
+ # between the site source and `paginate_path`.
109
+ #
110
+ # config - the site configuration hash
111
+ # page - the Jekyll::Page about which we're inquiring
112
+ #
113
+ # Returns true if the
114
+ def self.pagination_candidate?(config, page)
115
+ page_dir = File.dirname(File.expand_path(remove_leading_slash(page.path), config['source']))
116
+ paginate_path = remove_leading_slash(config['paginate_path'])
117
+ paginate_path = File.expand_path(paginate_path, config['source'])
118
+ page.name == 'index.html' &&
119
+ in_hierarchy(config['source'], page_dir, File.dirname(paginate_path))
120
+ end
121
+
122
+ # Determine if the subdirectories of the two paths are the same relative to source
123
+ #
124
+ # source - the site source
125
+ # page_dir - the directory of the Jekyll::Page
126
+ # paginate_path - the absolute paginate path (from root of FS)
127
+ #
128
+ # Returns whether the subdirectories are the same relative to source
129
+ def self.in_hierarchy(source, page_dir, paginate_path)
130
+ return false if paginate_path == File.dirname(paginate_path)
131
+ return false if paginate_path == Pathname.new(source).parent
132
+ page_dir == paginate_path ||
133
+ in_hierarchy(source, page_dir, File.dirname(paginate_path))
134
+ end
135
+
136
+ # Static: Return the pagination path of the page
137
+ #
138
+ # site - the Jekyll::Site object
139
+ # num_page - the pagination page number
140
+ #
141
+ # Returns the pagination path as a string
142
+ def self.paginate_path(site, num_page)
143
+ return nil if num_page.nil?
144
+ return Generators::Pagination.first_page_url(site) if num_page <= 1
145
+ format = site.config['paginate_path']
146
+ format = format.sub(':num', num_page.to_s)
147
+ ensure_leading_slash(format)
148
+ end
149
+
150
+ # Static: Return a String version of the input which has a leading slash.
151
+ # If the input already has a forward slash in position zero, it will be
152
+ # returned unchanged.
153
+ #
154
+ # path - a String path
155
+ #
156
+ # Returns the path with a leading slash
157
+ def self.ensure_leading_slash(path)
158
+ path[0..0] == "/" ? path : "/#{path}"
159
+ end
160
+
161
+ # Static: Return a String version of the input without a leading slash.
162
+ #
163
+ # path - a String path
164
+ #
165
+ # Returns the input without the leading slash
166
+ def self.remove_leading_slash(path)
167
+ ensure_leading_slash(path)[1..-1]
168
+ end
169
+
170
+ # Initialize a new Pager.
171
+ #
172
+ # site - the Jekyll::Site object
173
+ # page - The Integer page number.
174
+ # all_posts - The Array of all the site's Posts.
175
+ # num_pages - The Integer number of pages or nil if you'd like the number
176
+ # of pages calculated.
177
+ def initialize(site, page, all_posts, num_pages = nil)
178
+ @page = page
179
+ @per_page = site.config['paginate'].to_i
180
+ @total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page)
181
+
182
+ if @page > @total_pages
183
+ raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
184
+ end
185
+
186
+ init = (@page - 1) * @per_page
187
+ offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1)
188
+
189
+ @total_posts = all_posts.size
190
+ @posts = all_posts[init..offset]
191
+ @previous_page = @page != 1 ? @page - 1 : nil
192
+ @previous_page_path = Pager.paginate_path(site, @previous_page)
193
+ @next_page = @page != @total_pages ? @page + 1 : nil
194
+ @next_page_path = Pager.paginate_path(site, @next_page)
195
+ end
196
+
197
+ # Convert this Pager's data to a Hash suitable for use by Liquid.
198
+ #
199
+ # Returns the Hash representation of this Pager.
200
+ def to_liquid
201
+ {
202
+ 'page' => page,
203
+ 'per_page' => per_page,
204
+ 'posts' => posts,
205
+ 'total_posts' => total_posts,
206
+ 'total_pages' => total_pages,
207
+ 'previous_page' => previous_page,
208
+ 'previous_page_path' => previous_page_path,
209
+ 'next_page' => next_page,
210
+ 'next_page_path' => next_page_path
211
+ }
212
+ end
213
+ end
214
+ end